From 4ea10b3de6a65e6bf58effd1411342d406dbb1cb Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 24 Dec 2020 21:56:15 +0300 Subject: [PATCH 01/31] Pass promise to MessagesManager::add_pending_update. --- td/telegram/MessagesManager.cpp | 81 ++++++++++++++++++++------------- td/telegram/MessagesManager.h | 9 ++-- td/telegram/UpdatesManager.cpp | 29 +++++------- 3 files changed, 67 insertions(+), 52 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 141bebb6a..72045c2a4 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -660,7 +660,8 @@ class UnpinAllMessagesQuery : public Td::ResultHandler { "unpin all messages"); } else { td->messages_manager_->add_pending_update(make_tl_object(), affected_history->pts_, - affected_history->pts_count_, false, "unpin all messages"); + affected_history->pts_count_, false, Promise(), + "unpin all messages"); } } @@ -1556,7 +1557,8 @@ class ReadMessagesContentsQuery : public Td::ResultHandler { if (affected_messages->pts_count_ > 0) { td->messages_manager_->add_pending_update(make_tl_object(), affected_messages->pts_, - affected_messages->pts_count_, false, "read messages content query"); + affected_messages->pts_count_, false, Promise(), + "read messages content query"); } promise_.set_value(Unit()); @@ -1773,7 +1775,8 @@ class ReadHistoryQuery : public Td::ResultHandler { if (affected_messages->pts_count_ > 0) { td->messages_manager_->add_pending_update(make_tl_object(), affected_messages->pts_, - affected_messages->pts_count_, false, "read history query"); + affected_messages->pts_count_, false, Promise(), + "read history query"); } promise_.set_value(Unit()); @@ -2242,7 +2245,8 @@ class DeleteHistoryQuery : public Td::ResultHandler { if (affected_history->pts_count_ > 0) { td->messages_manager_->add_pending_update(make_tl_object(), affected_history->pts_, - affected_history->pts_count_, false, "delete history query"); + affected_history->pts_count_, false, Promise(), + "delete history query"); } if (affected_history->offset_ > 0) { @@ -2441,7 +2445,8 @@ class ReadAllMentionsQuery : public Td::ResultHandler { td->updates_manager_->get_difference("Wrong messages_readMentions result"); } else { td->messages_manager_->add_pending_update(make_tl_object(), affected_history->pts_, - affected_history->pts_count_, false, "read all mentions query"); + affected_history->pts_count_, false, Promise(), + "read all mentions query"); } } @@ -2577,7 +2582,7 @@ class SendMessageActor : public NetActorOnce { td->messages_manager_->add_pending_update( make_tl_object(random_id_, message_id, sent_message->date_), sent_message->pts_, - sent_message->pts_count_, false, "send message actor"); + sent_message->pts_count_, false, Promise(), "send message actor"); } void on_error(uint64 id, Status status) override { @@ -3582,7 +3587,8 @@ class DeleteMessagesQuery : public Td::ResultHandler { if (affected_messages->pts_count_ > 0) { td->messages_manager_->add_pending_update(make_tl_object(), affected_messages->pts_, - affected_messages->pts_count_, false, "delete messages query"); + affected_messages->pts_count_, false, Promise(), + "delete messages query"); } if (--query_count_ == 0) { promise_.set_value(Unit()); @@ -6122,7 +6128,7 @@ void MessagesManager::skip_old_pending_update(tl_object_ptr &&update, int32 new_pts, int32 pts_count, - bool force_apply, const char *source) { + bool force_apply, Promise &&promise, const char *source) { // do not try to run getDifference from this function CHECK(update != nullptr); CHECK(source != nullptr); @@ -6131,7 +6137,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u if (pts_count < 0 || new_pts <= pts_count) { LOG(ERROR) << "Receive update with wrong pts = " << new_pts << " or pts_count = " << pts_count << " from " << source << ": " << oneline(to_string(update)); - return; + return promise.set_value(Unit()); } // TODO need to save all updates that can change result of running queries not associated with pts (for example @@ -6148,7 +6154,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u auto update_new_message = static_cast(update.get()); DialogId dialog_id = get_message_dialog_id(update_new_message->message_); if (!check_update_dialog_id(update, dialog_id)) { - return; + return promise.set_value(Unit()); } break; } @@ -6156,7 +6162,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u auto update_read_history_inbox = static_cast(update.get()); auto dialog_id = DialogId(update_read_history_inbox->peer_); if (!check_update_dialog_id(update, dialog_id)) { - return; + return promise.set_value(Unit()); } break; } @@ -6164,7 +6170,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u auto update_read_history_outbox = static_cast(update.get()); auto dialog_id = DialogId(update_read_history_outbox->peer_); if (!check_update_dialog_id(update, dialog_id)) { - return; + return promise.set_value(Unit()); } break; } @@ -6172,7 +6178,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u auto update_edit_message = static_cast(update.get()); DialogId dialog_id = get_message_dialog_id(update_edit_message->message_); if (!check_update_dialog_id(update, dialog_id)) { - return; + return promise.set_value(Unit()); } break; } @@ -6180,7 +6186,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u auto update_pinned_messages = static_cast(update.get()); auto dialog_id = DialogId(update_pinned_messages->peer_); if (!check_update_dialog_id(update, dialog_id)) { - return; + return promise.set_value(Unit()); } break; } @@ -6190,17 +6196,18 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u } if (force_apply) { - CHECK(pending_updates_.empty()); + CHECK(pending_pts_updates_.empty()); CHECK(accumulated_pts_ == -1); if (pts_count != 0) { LOG(ERROR) << "Receive forced update with pts_count = " << pts_count << " from " << source; } process_update(std::move(update)); - return; + return promise.set_value(Unit()); } if (DROP_UPDATES) { - return set_get_difference_timeout(1.0); + set_get_difference_timeout(1.0); + return promise.set_value(Unit()); } int32 old_pts = td_->updates_manager_->get_pts(); @@ -6226,14 +6233,17 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u if (new_pts <= old_pts) { skip_old_pending_update(std::move(update), new_pts, old_pts, pts_count, source); - return; + return promise.set_value(Unit()); } if (td_->updates_manager_->running_get_difference()) { LOG(INFO) << "Save pending update got while running getDifference from " << source; CHECK(update->get_id() == dummyUpdate::ID || update->get_id() == updateSentMessage::ID); if (pts_count > 0) { - postponed_pts_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count)); + postponed_pts_updates_.emplace(new_pts, + PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); + } else { + promise.set_value(Unit()); } return; } @@ -6242,6 +6252,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u LOG(WARNING) << "Have old_pts (= " << old_pts << ") + pts_count (= " << pts_count << ") > new_pts (= " << new_pts << "). Logged in " << G()->shared_config().get_option_integer("authorization_date") << ". Update from " << source << " = " << oneline(to_string(update)); + promise.set_value(Unit()); // TODO postpone set_get_difference_timeout(0.001); return; } @@ -6257,13 +6268,14 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u << ", pts_count = " << pts_count << ". Logged in " << G()->shared_config().get_option_integer("authorization_date") << ". Update from " << source << " = " << oneline(to_string(update)); + promise.set_value(Unit()); // TODO postpone set_get_difference_timeout(0.001); return; } LOG_IF(INFO, pts_count == 0 && update->get_id() != dummyUpdate::ID) << "Skip useless update " << to_string(update); - if (pending_updates_.empty() && old_pts + accumulated_pts_count_ == accumulated_pts_ && + if (pending_pts_updates_.empty() && old_pts + accumulated_pts_count_ == accumulated_pts_ && !pts_gap_timeout_.has_timeout()) { if (pts_count > 0) { process_update(std::move(update)); @@ -6273,11 +6285,12 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u accumulated_pts_count_ = 0; accumulated_pts_ = -1; } + promise.set_value(Unit()); return; } if (pts_count > 0) { - pending_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count)); + pending_pts_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); } if (old_pts + accumulated_pts_count_ < accumulated_pts_) { @@ -6286,7 +6299,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u } CHECK(old_pts + accumulated_pts_count_ == accumulated_pts_); - if (!pending_updates_.empty()) { + if (!pending_pts_updates_.empty()) { process_pending_updates(); } } @@ -7193,7 +7206,8 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p if (running_get_channel_difference(dialog_id)) { if (pts_count > 0) { - d->postponed_channel_updates.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count)); + d->postponed_channel_updates.emplace(new_pts, + PendingPtsUpdate(std::move(update), new_pts, pts_count, Promise())); } LOG(INFO) << "Postpone channel update, because getChannelDifference is run"; return; @@ -7204,7 +7218,8 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p << ", pts_count = " << pts_count << " in update from " << source; if (pts_count > 0) { - d->postponed_channel_updates.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count)); + d->postponed_channel_updates.emplace(new_pts, + PendingPtsUpdate(std::move(update), new_pts, pts_count, Promise())); } get_channel_difference(dialog_id, old_pts, true, "add_pending_channel_update pts mismatch"); @@ -7410,8 +7425,9 @@ void MessagesManager::on_message_edited(FullMessageId full_message_id) { } void MessagesManager::process_pending_updates() { - for (auto &update : pending_updates_) { + for (auto &update : pending_pts_updates_) { process_update(std::move(update.second.update)); + update.second.promise.set_value(Unit()); } td_->updates_manager_->set_pts(accumulated_pts_, "process pending updates") @@ -7423,7 +7439,7 @@ void MessagesManager::drop_pending_updates() { accumulated_pts_count_ = 0; accumulated_pts_ = -1; pts_gap_timeout_.cancel_timeout(); - pending_updates_.clear(); + pending_pts_updates_.clear(); } string MessagesManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) { @@ -8749,8 +8765,8 @@ void MessagesManager::before_get_difference() { // scheduled messages are not returned in getDifference, so we must always reget them after it scheduled_messages_sync_generation_++; - postponed_pts_updates_.insert(std::make_move_iterator(pending_updates_.begin()), - std::make_move_iterator(pending_updates_.end())); + postponed_pts_updates_.insert(std::make_move_iterator(pending_pts_updates_.begin()), + std::make_move_iterator(pending_pts_updates_.end())); drop_pending_updates(); } @@ -8766,9 +8782,10 @@ void MessagesManager::after_get_difference() { if (new_pts <= old_pts) { skip_old_pending_update(std::move(update.second.update), new_pts, old_pts, update.second.pts_count, "after get difference"); + update.second.promise.set_value(Unit()); } else { add_pending_update(std::move(update.second.update), update.second.pts, update.second.pts_count, false, - "after get difference"); + std::move(update.second.promise), "after get difference"); } CHECK(!td_->updates_manager_->running_get_difference()); } @@ -8838,13 +8855,13 @@ void MessagesManager::after_get_difference() { const Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); - if (dialog_id.get_type() == DialogType::Channel || pending_updates_.empty() || message_id.is_scheduled() || + if (dialog_id.get_type() == DialogType::Channel || pending_pts_updates_.empty() || message_id.is_scheduled() || message_id <= d->last_new_message_id) { LOG(ERROR) << "Receive updateMessageId from " << it.second << " to " << full_message_id << " but not receive corresponding message, last_new_message_id = " << d->last_new_message_id; } if (dialog_id.get_type() != DialogType::Channel && - (pending_updates_.empty() || message_id.is_scheduled() || message_id <= d->last_new_message_id)) { + (pending_pts_updates_.empty() || message_id.is_scheduled() || message_id <= d->last_new_message_id)) { dump_debug_message_op(get_dialog(dialog_id)); } if (message_id.is_scheduled() || message_id <= d->last_new_message_id) { @@ -24454,6 +24471,8 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess FileId thumbnail_file_id, bool was_uploaded, bool was_thumbnail_uploaded, string file_reference, int32 schedule_date, uint64 generation, Result &&result) { + // must not run getDifference + CHECK(message_id.is_any_server()); auto m = get_message({dialog_id, message_id}); if (m == nullptr || m->edit_generation != generation) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 16c653ed9..47a9de98f 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -793,7 +793,7 @@ class MessagesManager : public Actor { bool skip_not_found); void add_pending_update(tl_object_ptr &&update, int32 new_pts, int32 pts_count, - bool force_apply, const char *source); + bool force_apply, Promise &&promise, const char *source); void add_pending_channel_update(DialogId dialog_id, tl_object_ptr &&update, int32 new_pts, int32 pts_count, const char *source, bool is_postponed_update = false); @@ -973,9 +973,10 @@ class MessagesManager : public Actor { tl_object_ptr update; int32 pts; int32 pts_count; + Promise promise; - PendingPtsUpdate(tl_object_ptr &&update, int32 pts, int32 pts_count) - : update(std::move(update)), pts(pts), pts_count(pts_count) { + PendingPtsUpdate(tl_object_ptr &&update, int32 pts, int32 pts_count, Promise &&promise) + : update(std::move(update)), pts(pts), pts_count(pts_count), promise(std::move(promise)) { } }; @@ -3107,7 +3108,7 @@ class MessagesManager : public Actor { bool running_get_difference_ = false; // true after before_get_difference and false after after_get_difference std::unordered_map, DialogIdHash> dialogs_; - std::multimap pending_updates_; + std::multimap pending_pts_updates_; std::multimap postponed_pts_updates_; std::unordered_set diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index c0ffbe72d..123446170 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1695,8 +1695,8 @@ void UpdatesManager::on_update(tl_object_ptr upd Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, "on_updateNewMessage"); - promise.set_value(Unit()); + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), + "on_updateNewMessage"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1721,18 +1721,16 @@ void UpdatesManager::on_update(tl_object_ptr &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updateReadMessagesContents"); - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updateEditMessage"); - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1741,12 +1739,12 @@ void UpdatesManager::on_update(tl_object_ptr int pts_count = update->pts_count_; if (update->messages_.empty()) { td_->messages_manager_->add_pending_update(make_tl_object(), new_pts, pts_count, force_apply, - "on_updateDeleteMessages"); + Promise(), "on_updateDeleteMessages"); + promise.set_value(Unit()); } else { - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updateDeleteMessages"); } - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1756,18 +1754,16 @@ void UpdatesManager::on_update(tl_object_ptrstill_unread_count_ = -1; } - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updateReadHistoryInbox"); - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updateReadHistoryOutbox"); - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1893,9 +1889,8 @@ void UpdatesManager::on_update(tl_object_ptr Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, + td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), "on_updatePinnedMessages"); - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1960,7 +1955,7 @@ void UpdatesManager::on_update(tl_object_ptr update Promise &&promise) { td_->web_pages_manager_->on_get_web_page(std::move(update->webpage_), DialogId()); td_->messages_manager_->add_pending_update(make_tl_object(), update->pts_, update->pts_count_, - force_apply, "on_updateWebPage"); + force_apply, Promise(), "on_updateWebPage"); promise.set_value(Unit()); } @@ -1987,7 +1982,7 @@ void UpdatesManager::on_update(tl_object_ptr up } td_->messages_manager_->add_pending_update(make_tl_object(), update->pts_, update->pts_count_, - force_apply, "on_updateFolderPeers"); + force_apply, Promise(), "on_updateFolderPeers"); promise.set_value(Unit()); } From 3dbc996accf5c7e12c338b4bd31c0cef0ed68f15 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 24 Dec 2020 22:09:44 +0300 Subject: [PATCH 02/31] Postpone pts updates, which can't be applied right now. --- td/telegram/MessagesManager.cpp | 24 +++++++++++++++--------- td/telegram/MessagesManager.h | 3 +++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 72045c2a4..ff0a9b959 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6236,15 +6236,10 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u return promise.set_value(Unit()); } - if (td_->updates_manager_->running_get_difference()) { + if (td_->updates_manager_->running_get_difference() || !postponed_pts_updates_.empty()) { LOG(INFO) << "Save pending update got while running getDifference from " << source; CHECK(update->get_id() == dummyUpdate::ID || update->get_id() == updateSentMessage::ID); - if (pts_count > 0) { - postponed_pts_updates_.emplace(new_pts, - PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); - } else { - promise.set_value(Unit()); - } + postpone_pts_update(std::move(update), new_pts, pts_count, std::move(promise)); return; } @@ -6252,7 +6247,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u LOG(WARNING) << "Have old_pts (= " << old_pts << ") + pts_count (= " << pts_count << ") > new_pts (= " << new_pts << "). Logged in " << G()->shared_config().get_option_integer("authorization_date") << ". Update from " << source << " = " << oneline(to_string(update)); - promise.set_value(Unit()); // TODO postpone + postpone_pts_update(std::move(update), new_pts, pts_count, std::move(promise)); set_get_difference_timeout(0.001); return; } @@ -6268,7 +6263,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u << ", pts_count = " << pts_count << ". Logged in " << G()->shared_config().get_option_integer("authorization_date") << ". Update from " << source << " = " << oneline(to_string(update)); - promise.set_value(Unit()); // TODO postpone + postpone_pts_update(std::move(update), new_pts, pts_count, std::move(promise)); set_get_difference_timeout(0.001); return; } @@ -6291,6 +6286,8 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u if (pts_count > 0) { pending_pts_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); + } else { + promise.set_value(Unit()); } if (old_pts + accumulated_pts_count_ < accumulated_pts_) { @@ -7442,6 +7439,15 @@ void MessagesManager::drop_pending_updates() { pending_pts_updates_.clear(); } +void MessagesManager::postpone_pts_update(tl_object_ptr &&update, int32 pts, int32 pts_count, + Promise &&promise) { + if (pts_count > 0) { + postponed_pts_updates_.emplace(pts, PendingPtsUpdate(std::move(update), pts, pts_count, std::move(promise))); + } else { + promise.set_value(Unit()); + } +} + string MessagesManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) { switch (scope) { case NotificationSettingsScope::Private: diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 47a9de98f..a4ccebee8 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2797,6 +2797,9 @@ class MessagesManager : public Actor { void drop_pending_updates(); + void postpone_pts_update(tl_object_ptr &&update, int32 pts, int32 pts_count, + Promise &&promise); + static string get_channel_pts_key(DialogId dialog_id); int32 load_channel_pts(DialogId dialog_id) const; From 4a28b980227599aff4622b75f7349813f5710944 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 00:14:18 +0300 Subject: [PATCH 03/31] Pass promise to add_pending_channel_update. --- td/telegram/MessagesManager.cpp | 98 +++++++++++++++++++-------------- td/telegram/MessagesManager.h | 9 ++- td/telegram/UpdatesManager.cpp | 16 +++--- 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index ff0a9b959..78f035c92 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -654,23 +654,24 @@ class UnpinAllMessagesQuery : public Td::ResultHandler { if (affected_history->pts_count_ > 0) { affected_history->pts_count_ = 0; // force receiving real updates from the server + auto promise = affected_history->offset_ > 0 ? Promise() : std::move(promise_); if (dialog_id_.get_type() == DialogType::Channel) { td->messages_manager_->add_pending_channel_update(dialog_id_, make_tl_object(), affected_history->pts_, affected_history->pts_count_, - "unpin all messages"); + std::move(promise), "unpin all messages"); } else { td->messages_manager_->add_pending_update(make_tl_object(), affected_history->pts_, - affected_history->pts_count_, false, Promise(), + affected_history->pts_count_, false, std::move(promise), "unpin all messages"); } + } else if (affected_history->offset_ <= 0) { + promise_.set_value(Unit()); } if (affected_history->offset_ > 0) { send_request(); return; } - - promise_.set_value(Unit()); } void on_error(uint64 id, Status status) override { @@ -2385,17 +2386,17 @@ class DeleteUserHistoryQuery : public Td::ResultHandler { CHECK(affected_history->get_id() == telegram_api::messages_affectedHistory::ID); if (affected_history->pts_count_ > 0) { - td->messages_manager_->add_pending_channel_update(DialogId(channel_id_), make_tl_object(), - affected_history->pts_, affected_history->pts_count_, - "delete user history query"); + td->messages_manager_->add_pending_channel_update( + DialogId(channel_id_), make_tl_object(), affected_history->pts_, affected_history->pts_count_, + affected_history->offset_ > 0 ? Promise() : std::move(promise_), "delete user history query"); + } else if (affected_history->offset_ <= 0) { + promise_.set_value(Unit()); } if (affected_history->offset_ > 0) { send_request(); return; } - - promise_.set_value(Unit()); } void on_error(uint64 id, Status status) override { @@ -2576,7 +2577,7 @@ class SendMessageActor : public NetActorOnce { if (dialog_id_.get_type() == DialogType::Channel) { td->messages_manager_->add_pending_channel_update( dialog_id_, make_tl_object(random_id_, message_id, sent_message->date_), - sent_message->pts_, sent_message->pts_count_, "send message actor"); + sent_message->pts_, sent_message->pts_count_, Promise(), "send message actor"); return; } @@ -3651,7 +3652,7 @@ class DeleteChannelMessagesQuery : public Td::ResultHandler { if (affected_messages->pts_count_ > 0) { td->messages_manager_->add_pending_channel_update(DialogId(channel_id_), make_tl_object(), affected_messages->pts_, affected_messages->pts_count_, - "DeleteChannelMessagesQuery"); + Promise(), "DeleteChannelMessagesQuery"); } if (--query_count_ == 0) { promise_.set_value(Unit()); @@ -6399,17 +6400,20 @@ void MessagesManager::on_update_service_notification(tl_object_ptr &&update) { +void MessagesManager::on_update_new_channel_message(tl_object_ptr &&update, + Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; DialogId dialog_id = get_message_dialog_id(update->message_); switch (dialog_id.get_type()) { case DialogType::None: + promise.set_value(Unit()); return; case DialogType::User: case DialogType::Chat: case DialogType::SecretChat: LOG(ERROR) << "Receive updateNewChannelMessage in wrong " << dialog_id; + promise.set_value(Unit()); return; case DialogType::Channel: { auto channel_id = dialog_id.get_channel_id(); @@ -6417,6 +6421,7 @@ void MessagesManager::on_update_new_channel_message(tl_object_ptrcontacts_manager_->have_min_channel(channel_id)) { td_->updates_manager_->schedule_get_difference("on_update_new_channel_message"); + promise.set_value(Unit()); // TODO postpone return; } } @@ -6428,26 +6433,24 @@ void MessagesManager::on_update_new_channel_message(tl_object_ptr &&update) { +void MessagesManager::on_update_edit_channel_message(tl_object_ptr &&update, + Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; DialogId dialog_id = get_message_dialog_id(update->message_); switch (dialog_id.get_type()) { case DialogType::None: + promise.set_value(Unit()); return; case DialogType::User: case DialogType::Chat: case DialogType::SecretChat: LOG(ERROR) << "Receive updateEditChannelMessage in wrong " << dialog_id; + promise.set_value(Unit()); return; case DialogType::Channel: { auto channel_id = dialog_id.get_channel_id(); @@ -6455,6 +6458,7 @@ void MessagesManager::on_update_edit_channel_message(tl_object_ptrcontacts_manager_->have_min_channel(channel_id)) { td_->updates_manager_->schedule_get_difference("on_update_edit_channel_message"); + promise.set_value(Unit()); // TODO postpone return; } } @@ -6466,13 +6470,8 @@ void MessagesManager::on_update_edit_channel_message(tl_object_ptr &&update) { @@ -7123,19 +7122,20 @@ void MessagesManager::cancel_user_dialog_action(DialogId dialog_id, const Messag } void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_ptr &&update, - int32 new_pts, int32 pts_count, const char *source, - bool is_postponed_update) { + int32 new_pts, int32 pts_count, Promise &&promise, + const char *source, bool is_postponed_update) { LOG(INFO) << "Receive from " << source << " pending " << to_string(update); CHECK(update != nullptr); CHECK(dialog_id.get_type() == DialogType::Channel); if (pts_count < 0 || new_pts <= pts_count) { LOG(ERROR) << "Receive channel update from " << source << " with wrong pts = " << new_pts << " or pts_count = " << pts_count << ": " << oneline(to_string(update)); + promise.set_value(Unit()); return; } // TODO need to save all updates that can change result of running queries not associated with pts (for example - // getHistory) and apply them to result of this queries + // getHistory) and apply them to result of these queries Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { @@ -7145,6 +7145,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p if (!td_->contacts_manager_->have_channel(channel_id)) { // do not create dialog if there is no info about the channel LOG(INFO) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update)); + promise.set_value(Unit()); return; } @@ -7158,6 +7159,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p // if there is no dialog, it can be created by the update LOG(INFO) << "Receive pending update from " << source << " about unknown " << dialog_id; if (running_get_channel_difference(dialog_id)) { + promise.set_value(Unit()); return; } } else { @@ -7182,6 +7184,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p // apply sent channel message on_get_message(std::move(update_new_channel_message->message_), true, true, false, true, true, "updateNewChannelMessage with an awaited message"); + promise.set_value(Unit()); return; } } @@ -7191,6 +7194,7 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p // apply sent channel message on_send_message_success(update_sent_message->random_id_, update_sent_message->message_id_, update_sent_message->date_, FileId(), "process old updateSentChannelMessage"); + promise.set_value(Unit()); return; } } @@ -7198,13 +7202,14 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p LOG_IF(WARNING, new_pts == old_pts && pts_count == 0) << "Receive from " << source << " useless channel update " << oneline(to_string(update)); LOG(INFO) << "Skip already applied channel update"; + promise.set_value(Unit()); return; } if (running_get_channel_difference(dialog_id)) { if (pts_count > 0) { - d->postponed_channel_updates.emplace(new_pts, - PendingPtsUpdate(std::move(update), new_pts, pts_count, Promise())); + d->postponed_channel_updates.emplace( + new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); } LOG(INFO) << "Postpone channel update, because getChannelDifference is run"; return; @@ -7215,8 +7220,8 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p << ", pts_count = " << pts_count << " in update from " << source; if (pts_count > 0) { - d->postponed_channel_updates.emplace(new_pts, - PendingPtsUpdate(std::move(update), new_pts, pts_count, Promise())); + d->postponed_channel_updates.emplace( + new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); } get_channel_difference(dialog_id, old_pts, true, "add_pending_channel_update pts mismatch"); @@ -7236,12 +7241,14 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p d = get_dialog(dialog_id); if (d == nullptr) { LOG(INFO) << "Update didn't created " << dialog_id; + promise.set_value(Unit()); return; } } CHECK(new_pts > d->pts); set_channel_pts(d, new_pts, source); + promise.set_value(Unit()); } bool MessagesManager::is_old_channel_update(DialogId dialog_id, int32 new_pts) { @@ -35182,31 +35189,42 @@ void MessagesManager::after_get_channel_difference(DialogId dialog_id, bool succ auto d = get_dialog(dialog_id); if (d != nullptr) { bool have_access = have_input_peer(dialog_id, AccessRights::Read); - if (!have_access) { - d->postponed_channel_updates.clear(); - } else if (!d->postponed_channel_updates.empty()) { + if (!d->postponed_channel_updates.empty()) { LOG(INFO) << "Begin to apply postponed channel updates"; while (!d->postponed_channel_updates.empty()) { auto it = d->postponed_channel_updates.begin(); auto update = std::move(it->second.update); auto update_pts = it->second.pts; auto update_pts_count = it->second.pts_count; + auto promise = std::move(it->second.promise); d->postponed_channel_updates.erase(it); + auto old_size = d->postponed_channel_updates.size(); auto update_id = update->get_id(); - add_pending_channel_update(dialog_id, std::move(update), update_pts, update_pts_count, - "apply postponed channel updates", true); + if (have_access) { + add_pending_channel_update(dialog_id, std::move(update), update_pts, update_pts_count, std::move(promise), + "apply postponed channel updates", true); + } else { + promise.set_value(Unit()); + } if (d->postponed_channel_updates.size() != old_size || running_get_channel_difference(dialog_id)) { if (success && update_pts < d->pts + 10000 && update_pts_count == 1) { // if getChannelDifference was successful and update pts is near channel pts, // we hope that the update eventually can be applied LOG(INFO) << "Can't apply postponed channel updates"; } else { - // otherwise we protecting from getChannelDifference repeating calls by dropping pending updates + // otherwise protect from getChannelDifference repeating calls by dropping postponed updates LOG(WARNING) << "Failed to apply postponed updates of type " << update_id << " in " << dialog_id << " with pts " << d->pts << ", update pts is " << update_pts << ", update pts count is " << update_pts_count; + vector> update_promises; + for (auto &postponed_update : d->postponed_channel_updates) { + update_promises.push_back(std::move(postponed_update.second.promise)); + } d->postponed_channel_updates.clear(); + for (auto &update_promise : update_promises) { + update_promise.set_value(Unit()); + } } break; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index a4ccebee8..09a626999 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -343,9 +343,11 @@ class MessagesManager : public Actor { void on_update_service_notification(tl_object_ptr &&update, bool skip_new_entities, Promise &&promise); - void on_update_new_channel_message(tl_object_ptr &&update); + void on_update_new_channel_message(tl_object_ptr &&update, + Promise &&promise); - void on_update_edit_channel_message(tl_object_ptr &&update); + void on_update_edit_channel_message(tl_object_ptr &&update, + Promise &&promise); void on_update_read_channel_inbox(tl_object_ptr &&update); @@ -796,7 +798,8 @@ class MessagesManager : public Actor { bool force_apply, Promise &&promise, const char *source); void add_pending_channel_update(DialogId dialog_id, tl_object_ptr &&update, int32 new_pts, - int32 pts_count, const char *source, bool is_postponed_update = false); + int32 pts_count, Promise &&promise, const char *source, + bool is_postponed_update = false); bool is_old_channel_update(DialogId dialog_id, int32 new_pts); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 123446170..854809e0f 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1701,8 +1701,7 @@ void UpdatesManager::on_update(tl_object_ptr upd void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - td_->messages_manager_->on_update_new_channel_message(std::move(update)); - promise.set_value(Unit()); + td_->messages_manager_->on_update_new_channel_message(std::move(update), std::move(promise)); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1812,8 +1811,7 @@ void UpdatesManager::on_update(tl_object_ptr update void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - td_->messages_manager_->on_update_edit_channel_message(std::move(update)); - promise.set_value(Unit()); + td_->messages_manager_->on_update_edit_channel_message(std::move(update), std::move(promise)); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1821,14 +1819,14 @@ void UpdatesManager::on_update(tl_object_ptrchannel_id_); if (!channel_id.is_valid()) { LOG(ERROR) << "Receive invalid " << channel_id; + promise.set_value(Unit()); } else { DialogId dialog_id(channel_id); int new_pts = update->pts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - "on_updateDeleteChannelMessages"); + std::move(promise), "on_updateDeleteChannelMessages"); } - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1898,14 +1896,14 @@ void UpdatesManager::on_update(tl_object_ptrchannel_id_); if (!channel_id.is_valid()) { LOG(ERROR) << "Receive invalid " << channel_id; + promise.set_value(Unit()); } else { DialogId dialog_id(channel_id); int new_pts = update->pts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - "on_updatePinnedChannelMessages"); + std::move(promise), "on_updatePinnedChannelMessages"); } - promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1968,7 +1966,7 @@ void UpdatesManager::on_update(tl_object_ptr } else { DialogId dialog_id(channel_id); td_->messages_manager_->add_pending_channel_update(dialog_id, make_tl_object(), update->pts_, - update->pts_count_, "on_updateChannelWebPage"); + update->pts_count_, Promise(), "on_updateChannelWebPage"); } promise.set_value(Unit()); } From d191bc49b6218afcba8c8450c8e58621f35c1b8a Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 00:26:02 +0300 Subject: [PATCH 04/31] Save updates with pts_count == 0 to postpone setting their promises. --- td/telegram/MessagesManager.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 78f035c92..2df041fa4 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6285,11 +6285,7 @@ void MessagesManager::add_pending_update(tl_object_ptr &&u return; } - if (pts_count > 0) { - pending_pts_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); - } else { - promise.set_value(Unit()); - } + pending_pts_updates_.emplace(new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); if (old_pts + accumulated_pts_count_ < accumulated_pts_) { set_get_difference_timeout(UpdatesManager::MAX_UNFILLED_GAP_TIME); @@ -7207,11 +7203,9 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p } if (running_get_channel_difference(dialog_id)) { - if (pts_count > 0) { - d->postponed_channel_updates.emplace( - new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); - } LOG(INFO) << "Postpone channel update, because getChannelDifference is run"; + d->postponed_channel_updates.emplace(new_pts, + PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); return; } @@ -7219,10 +7213,8 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p LOG(INFO) << "Found a gap in the " << dialog_id << " with pts = " << old_pts << ". new_pts = " << new_pts << ", pts_count = " << pts_count << " in update from " << source; - if (pts_count > 0) { - d->postponed_channel_updates.emplace( - new_pts, PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); - } + d->postponed_channel_updates.emplace(new_pts, + PendingPtsUpdate(std::move(update), new_pts, pts_count, std::move(promise))); get_channel_difference(dialog_id, old_pts, true, "add_pending_channel_update pts mismatch"); return; @@ -7448,11 +7440,7 @@ void MessagesManager::drop_pending_updates() { void MessagesManager::postpone_pts_update(tl_object_ptr &&update, int32 pts, int32 pts_count, Promise &&promise) { - if (pts_count > 0) { - postponed_pts_updates_.emplace(pts, PendingPtsUpdate(std::move(update), pts, pts_count, std::move(promise))); - } else { - promise.set_value(Unit()); - } + postponed_pts_updates_.emplace(pts, PendingPtsUpdate(std::move(update), pts, pts_count, std::move(promise))); } string MessagesManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) { From ba9837f55ed97d17430ae42d1ba6edd399d7a334 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 01:41:56 +0300 Subject: [PATCH 05/31] tg_cli: combine emp and empttl. --- td/telegram/cli.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 9305b7346..eaf032779 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3176,7 +3176,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(document), nullptr, false, as_caption("")))); - } else if (op == "emp") { + } else if (op == "emp" || op == "empttl") { string chat_id; string message_id; string photo; @@ -3185,17 +3185,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(photo), as_input_thumbnail(photo), Auto(), 0, 0, - as_caption(""), 0))); - } else if (op == "empttl") { - string chat_id; - string message_id; - string photo; - std::tie(chat_id, args) = split(args); - std::tie(message_id, photo) = split(args); - send_request(td_api::make_object( - as_chat_id(chat_id), as_message_id(message_id), nullptr, - td_api::make_object(as_input_file(photo), as_input_thumbnail(photo), Auto(), 0, 0, - as_caption(""), 10))); + as_caption(""), op == "empttl" ? 10 : 0))); } else if (op == "emvt") { string chat_id; string message_id; From b867a597e822cbb649fdb990e24c405bc356855d Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 02:37:14 +0300 Subject: [PATCH 06/31] Simplify add_pending_channel_update calls. --- td/telegram/MessagesManager.cpp | 6 ++++- td/telegram/UpdatesManager.cpp | 43 ++++++++++----------------------- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 2df041fa4..50a56051a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7122,7 +7122,11 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p const char *source, bool is_postponed_update) { LOG(INFO) << "Receive from " << source << " pending " << to_string(update); CHECK(update != nullptr); - CHECK(dialog_id.get_type() == DialogType::Channel); + if (dialog_id.get_type() != DialogType::Channel) { + LOG(ERROR) << "Receive update in invalid " << dialog_id << " from " << source << ": " << oneline(to_string(update)); + promise.set_value(Unit()); + return; + } if (pts_count < 0 || new_pts <= pts_count) { LOG(ERROR) << "Receive channel update from " << source << " with wrong pts = " << new_pts << " or pts_count = " << pts_count << ": " << oneline(to_string(update)); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 854809e0f..975a6c650 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1816,17 +1816,11 @@ void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - ChannelId channel_id(update->channel_id_); - if (!channel_id.is_valid()) { - LOG(ERROR) << "Receive invalid " << channel_id; - promise.set_value(Unit()); - } else { - DialogId dialog_id(channel_id); - int new_pts = update->pts_; - int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - std::move(promise), "on_updateDeleteChannelMessages"); - } + DialogId dialog_id(ChannelId(update->channel_id_)); + int new_pts = update->pts_; + int pts_count = update->pts_count_; + td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, + std::move(promise), "on_updateDeleteChannelMessages"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1893,17 +1887,11 @@ void UpdatesManager::on_update(tl_object_ptr void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - ChannelId channel_id(update->channel_id_); - if (!channel_id.is_valid()) { - LOG(ERROR) << "Receive invalid " << channel_id; - promise.set_value(Unit()); - } else { - DialogId dialog_id(channel_id); - int new_pts = update->pts_; - int pts_count = update->pts_count_; - td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - std::move(promise), "on_updatePinnedChannelMessages"); - } + DialogId dialog_id(ChannelId(update->channel_id_)); + int new_pts = update->pts_; + int pts_count = update->pts_count_; + td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, + std::move(promise), "on_updatePinnedChannelMessages"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1960,14 +1948,9 @@ void UpdatesManager::on_update(tl_object_ptr update void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { td_->web_pages_manager_->on_get_web_page(std::move(update->webpage_), DialogId()); - ChannelId channel_id(update->channel_id_); - if (!channel_id.is_valid()) { - LOG(ERROR) << "Receive invalid " << channel_id; - } else { - DialogId dialog_id(channel_id); - td_->messages_manager_->add_pending_channel_update(dialog_id, make_tl_object(), update->pts_, - update->pts_count_, Promise(), "on_updateChannelWebPage"); - } + DialogId dialog_id(ChannelId(update->channel_id_)); + td_->messages_manager_->add_pending_channel_update(dialog_id, make_tl_object(), update->pts_, + update->pts_count_, Promise(), "on_updateChannelWebPage"); promise.set_value(Unit()); } From a8377db05de76270994e618e55ae64e3f6bab221 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 02:53:00 +0300 Subject: [PATCH 07/31] Simplify handling of updateNewChannelMessage and updateEditChannelMessage. --- td/telegram/MessagesManager.cpp | 85 ++++----------------------------- td/telegram/MessagesManager.h | 6 --- td/telegram/UpdatesManager.cpp | 38 +++++++++------ 3 files changed, 32 insertions(+), 97 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 50a56051a..cc7661a32 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6396,80 +6396,6 @@ void MessagesManager::on_update_service_notification(tl_object_ptr &&update, - Promise &&promise) { - int new_pts = update->pts_; - int pts_count = update->pts_count_; - DialogId dialog_id = get_message_dialog_id(update->message_); - switch (dialog_id.get_type()) { - case DialogType::None: - promise.set_value(Unit()); - return; - case DialogType::User: - case DialogType::Chat: - case DialogType::SecretChat: - LOG(ERROR) << "Receive updateNewChannelMessage in wrong " << dialog_id; - promise.set_value(Unit()); - return; - case DialogType::Channel: { - auto channel_id = dialog_id.get_channel_id(); - if (!td_->contacts_manager_->have_channel(channel_id)) { - // if min channel was received - if (td_->contacts_manager_->have_min_channel(channel_id)) { - td_->updates_manager_->schedule_get_difference("on_update_new_channel_message"); - promise.set_value(Unit()); // TODO postpone - return; - } - } - // Ok - break; - } - default: - UNREACHABLE(); - return; - } - - add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, std::move(promise), - "on_update_new_channel_message"); -} - -void MessagesManager::on_update_edit_channel_message(tl_object_ptr &&update, - Promise &&promise) { - int new_pts = update->pts_; - int pts_count = update->pts_count_; - DialogId dialog_id = get_message_dialog_id(update->message_); - switch (dialog_id.get_type()) { - case DialogType::None: - promise.set_value(Unit()); - return; - case DialogType::User: - case DialogType::Chat: - case DialogType::SecretChat: - LOG(ERROR) << "Receive updateEditChannelMessage in wrong " << dialog_id; - promise.set_value(Unit()); - return; - case DialogType::Channel: { - auto channel_id = dialog_id.get_channel_id(); - if (!td_->contacts_manager_->have_channel(channel_id)) { - // if min channel was received - if (td_->contacts_manager_->have_min_channel(channel_id)) { - td_->updates_manager_->schedule_get_difference("on_update_edit_channel_message"); - promise.set_value(Unit()); // TODO postpone - return; - } - } - // Ok - break; - } - default: - UNREACHABLE(); - return; - } - - add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, std::move(promise), - "on_update_edit_channel_message"); -} - void MessagesManager::on_update_read_channel_inbox(tl_object_ptr &&update) { ChannelId channel_id(update->channel_id_); if (!channel_id.is_valid()) { @@ -7123,7 +7049,8 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p LOG(INFO) << "Receive from " << source << " pending " << to_string(update); CHECK(update != nullptr); if (dialog_id.get_type() != DialogType::Channel) { - LOG(ERROR) << "Receive update in invalid " << dialog_id << " from " << source << ": " << oneline(to_string(update)); + LOG(ERROR) << "Receive channel update in invalid " << dialog_id << " from " << source << ": " + << oneline(to_string(update)); promise.set_value(Unit()); return; } @@ -7134,6 +7061,13 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p return; } + auto channel_id = dialog_id.get_channel_id(); + if (!td_->contacts_manager_->have_channel(channel_id) && td_->contacts_manager_->have_min_channel(channel_id)) { + td_->updates_manager_->schedule_get_difference("on_update_new_channel_message"); + promise.set_value(Unit()); + return; + } + // TODO need to save all updates that can change result of running queries not associated with pts (for example // getHistory) and apply them to result of these queries @@ -7141,7 +7075,6 @@ void MessagesManager::add_pending_channel_update(DialogId dialog_id, tl_object_p if (d == nullptr) { auto pts = load_channel_pts(dialog_id); if (pts > 0) { - auto channel_id = dialog_id.get_channel_id(); if (!td_->contacts_manager_->have_channel(channel_id)) { // do not create dialog if there is no info about the channel LOG(INFO) << "There is no info about " << channel_id << ", so ignore " << oneline(to_string(update)); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 09a626999..c922b07c0 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -343,12 +343,6 @@ class MessagesManager : public Actor { void on_update_service_notification(tl_object_ptr &&update, bool skip_new_entities, Promise &&promise); - void on_update_new_channel_message(tl_object_ptr &&update, - Promise &&promise); - - void on_update_edit_channel_message(tl_object_ptr &&update, - Promise &&promise); - void on_update_read_channel_inbox(tl_object_ptr &&update); void on_update_read_channel_outbox(tl_object_ptr &&update); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 975a6c650..b8bdbd003 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1696,12 +1696,16 @@ void UpdatesManager::on_update(tl_object_ptr upd int new_pts = update->pts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateNewMessage"); + "updateNewMessage"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - td_->messages_manager_->on_update_new_channel_message(std::move(update), std::move(promise)); + DialogId dialog_id = MessagesManager::get_message_dialog_id(update->message_); + int new_pts = update->pts_; + int pts_count = update->pts_count_; + td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, + std::move(promise), "updateNewChannelMessage"); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1721,7 +1725,7 @@ void UpdatesManager::on_update(tl_object_ptrpts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateReadMessagesContents"); + "updateReadMessagesContents"); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1729,7 +1733,7 @@ void UpdatesManager::on_update(tl_object_ptr up int new_pts = update->pts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateEditMessage"); + "updateEditMessage"); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1738,11 +1742,11 @@ void UpdatesManager::on_update(tl_object_ptr int pts_count = update->pts_count_; if (update->messages_.empty()) { td_->messages_manager_->add_pending_update(make_tl_object(), new_pts, pts_count, force_apply, - Promise(), "on_updateDeleteMessages"); + Promise(), "updateDeleteMessages"); promise.set_value(Unit()); } else { td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateDeleteMessages"); + "updateDeleteMessages"); } } @@ -1754,7 +1758,7 @@ void UpdatesManager::on_update(tl_object_ptrstill_unread_count_ = -1; } td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateReadHistoryInbox"); + "updateReadHistoryInbox"); } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, @@ -1762,7 +1766,7 @@ void UpdatesManager::on_update(tl_object_ptrpts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updateReadHistoryOutbox"); + "updateReadHistoryOutbox"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1811,7 +1815,11 @@ void UpdatesManager::on_update(tl_object_ptr update void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise) { - td_->messages_manager_->on_update_edit_channel_message(std::move(update), std::move(promise)); + DialogId dialog_id = MessagesManager::get_message_dialog_id(update->message_); + int new_pts = update->pts_; + int pts_count = update->pts_count_; + td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, + std::move(promise), "updateEditChannelMessage"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1820,7 +1828,7 @@ void UpdatesManager::on_update(tl_object_ptrpts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - std::move(promise), "on_updateDeleteChannelMessages"); + std::move(promise), "updateDeleteChannelMessages"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1882,7 +1890,7 @@ void UpdatesManager::on_update(tl_object_ptr int new_pts = update->pts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, std::move(promise), - "on_updatePinnedMessages"); + "updatePinnedMessages"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1891,7 +1899,7 @@ void UpdatesManager::on_update(tl_object_ptrpts_; int pts_count = update->pts_count_; td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count, - std::move(promise), "on_updatePinnedChannelMessages"); + std::move(promise), "updatePinnedChannelMessages"); } void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, @@ -1941,7 +1949,7 @@ void UpdatesManager::on_update(tl_object_ptr update Promise &&promise) { td_->web_pages_manager_->on_get_web_page(std::move(update->webpage_), DialogId()); td_->messages_manager_->add_pending_update(make_tl_object(), update->pts_, update->pts_count_, - force_apply, Promise(), "on_updateWebPage"); + force_apply, Promise(), "updateWebPage"); promise.set_value(Unit()); } @@ -1950,7 +1958,7 @@ void UpdatesManager::on_update(tl_object_ptr td_->web_pages_manager_->on_get_web_page(std::move(update->webpage_), DialogId()); DialogId dialog_id(ChannelId(update->channel_id_)); td_->messages_manager_->add_pending_channel_update(dialog_id, make_tl_object(), update->pts_, - update->pts_count_, Promise(), "on_updateChannelWebPage"); + update->pts_count_, Promise(), "updateChannelWebPage"); promise.set_value(Unit()); } @@ -1963,7 +1971,7 @@ void UpdatesManager::on_update(tl_object_ptr up } td_->messages_manager_->add_pending_update(make_tl_object(), update->pts_, update->pts_count_, - force_apply, Promise(), "on_updateFolderPeers"); + force_apply, Promise(), "updateFolderPeers"); promise.set_value(Unit()); } From ebc4e57da7dcad1833aa52396379a9be8903e4a5 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 03:14:49 +0300 Subject: [PATCH 08/31] Minor improvements of process_update. --- td/telegram/MessagesManager.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index cc7661a32..2b30f9cff 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7201,11 +7201,12 @@ void MessagesManager::process_update(tl_object_ptr &&updat case dummyUpdate::ID: LOG(INFO) << "Process dummyUpdate"; break; - case telegram_api::updateNewMessage::ID: + case telegram_api::updateNewMessage::ID: { + auto update_new_message = move_tl_object_as(update); LOG(INFO) << "Process updateNewMessage"; - on_get_message(std::move(move_tl_object_as(update)->message_), true, false, false, - true, true, "updateNewMessage"); + on_get_message(std::move(update_new_message->message_), true, false, false, true, true, "updateNewMessage"); break; + } case updateSentMessage::ID: { auto send_message_success_update = move_tl_object_as(update); LOG(INFO) << "Process updateSentMessage " << send_message_success_update->random_id_; @@ -7222,9 +7223,9 @@ void MessagesManager::process_update(tl_object_ptr &&updat break; } case telegram_api::updateEditMessage::ID: { - auto full_message_id = - on_get_message(std::move(move_tl_object_as(update)->message_), false, false, - false, false, false, "updateEditMessage"); + auto update_edit_message = move_tl_object_as(update); + auto full_message_id = on_get_message(std::move(update_edit_message->message_), false, false, false, false, false, + "updateEditMessage"); LOG(INFO) << "Process updateEditMessage"; on_message_edited(full_message_id); break; @@ -7287,11 +7288,13 @@ void MessagesManager::process_channel_update(tl_object_ptr send_message_success_update->date_, FileId(), "process updateSentChannelMessage"); break; } - case telegram_api::updateNewChannelMessage::ID: + case telegram_api::updateNewChannelMessage::ID: { + auto update_new_channel_message = move_tl_object_as(update); LOG(INFO) << "Process updateNewChannelMessage"; - on_get_message(std::move(move_tl_object_as(update)->message_), true, true, - false, true, true, "updateNewChannelMessage"); + on_get_message(std::move(update_new_channel_message->message_), true, true, false, true, true, + "updateNewChannelMessage"); break; + } case telegram_api::updateDeleteChannelMessages::ID: { auto delete_channel_messages_update = move_tl_object_as(update); LOG(INFO) << "Process updateDeleteChannelMessages"; @@ -7311,10 +7314,10 @@ void MessagesManager::process_channel_update(tl_object_ptr break; } case telegram_api::updateEditChannelMessage::ID: { + auto update_edit_channel_message = move_tl_object_as(update); LOG(INFO) << "Process updateEditChannelMessage"; - auto full_message_id = - on_get_message(std::move(move_tl_object_as(update)->message_), false, - true, false, false, false, "updateEditChannelMessage"); + auto full_message_id = on_get_message(std::move(update_edit_channel_message->message_), false, true, false, false, + false, "updateEditChannelMessage"); on_message_edited(full_message_id); break; } From b70eb3315809255d75c3ff40031991cb946a117c Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 03:30:52 +0300 Subject: [PATCH 09/31] Save pts of the last processed message edit. --- td/telegram/MessagesManager.cpp | 10 ++++++---- td/telegram/MessagesManager.h | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 2b30f9cff..223c98b73 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -7227,7 +7227,7 @@ void MessagesManager::process_update(tl_object_ptr &&updat auto full_message_id = on_get_message(std::move(update_edit_message->message_), false, false, false, false, false, "updateEditMessage"); LOG(INFO) << "Process updateEditMessage"; - on_message_edited(full_message_id); + on_message_edited(full_message_id, update_edit_message->pts_); break; } case telegram_api::updateDeleteMessages::ID: { @@ -7318,7 +7318,7 @@ void MessagesManager::process_channel_update(tl_object_ptr LOG(INFO) << "Process updateEditChannelMessage"; auto full_message_id = on_get_message(std::move(update_edit_channel_message->message_), false, true, false, false, false, "updateEditChannelMessage"); - on_message_edited(full_message_id); + on_message_edited(full_message_id, update_edit_channel_message->pts_); break; } case telegram_api::updatePinnedChannelMessages::ID: { @@ -7344,15 +7344,16 @@ void MessagesManager::process_channel_update(tl_object_ptr } } -void MessagesManager::on_message_edited(FullMessageId full_message_id) { +void MessagesManager::on_message_edited(FullMessageId full_message_id, int32 pts) { if (full_message_id == FullMessageId()) { return; } auto dialog_id = full_message_id.get_dialog_id(); Dialog *d = get_dialog(dialog_id); - const Message *m = get_message(d, full_message_id.get_message_id()); + Message *m = get_message(d, full_message_id.get_message_id()); CHECK(m != nullptr); + m->last_edit_pts = pts; if (td_->auth_manager_->is_bot()) { d->last_edited_message_id = m->message_id; send_update_message_edited(dialog_id, m); @@ -32933,6 +32934,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me "update_message_content"); } old_content = std::move(new_content); + old_message->last_edit_pts = 0; 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_any_file_id(new_content.get())); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index c922b07c0..bded8144d 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1138,6 +1138,8 @@ class MessagesManager : public Actor { uint64 edit_generation = 0; Promise edit_promise; + int32 last_edit_pts = 0; + unique_ptr left; unique_ptr right; @@ -1828,7 +1830,7 @@ class MessagesManager : public Actor { void process_channel_update(tl_object_ptr &&update); - void on_message_edited(FullMessageId full_message_id); + void on_message_edited(FullMessageId full_message_id, int32 pts); void delete_messages_from_updates(const vector &message_ids); From 9ca42ec8da0e2f75d7f5fe3e3141a38df232a85f Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 16:12:09 +0300 Subject: [PATCH 10/31] Check message pts before merging files. --- td/telegram/MessagesManager.cpp | 33 +++++++++++++++++++++++++-------- td/telegram/MessagesManager.h | 2 +- td/telegram/UpdatesManager.cpp | 31 +++++++++++++++++++++++++++++++ td/telegram/UpdatesManager.h | 2 ++ 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 223c98b73..c5611499e 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -3034,11 +3034,20 @@ class SendScheduledMessageActor : public NetActorOnce { }; class EditMessageActor : public NetActorOnce { - Promise promise_; + Promise promise_; DialogId dialog_id_; public: - explicit EditMessageActor(Promise &&promise) : promise_(std::move(promise)) { + explicit EditMessageActor(Promise &&promise) { + promise_ = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(Unit()); + } + }); + } + explicit EditMessageActor(Promise &&promise) : promise_(std::move(promise)) { } void send(int32 flags, DialogId dialog_id, MessageId message_id, const string &text, @@ -3097,13 +3106,16 @@ class EditMessageActor : public NetActorOnce { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditMessageActor: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); + auto pts = td->updates_manager_->get_update_edit_message_pts(ptr.get()); + auto promise = PromiseCreator::lambda( + [promise = std::move(promise_), pts](Result result) mutable { promise.set_value(std::move(pts)); }); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise)); } void on_error(uint64 id, Status status) override { LOG(INFO) << "Receive error for EditMessageQuery: " << status; if (!td->auth_manager_->is_bot() && status.message() == "MESSAGE_NOT_MODIFIED") { - return promise_.set_value(Unit()); + return promise_.set_value(0); } td->messages_manager_->on_get_dialog_error(dialog_id_, status, "EditMessageActor"); promise_.set_error(std::move(status)); @@ -23257,7 +23269,7 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, const Messag auto promise = PromiseCreator::lambda( [actor_id = actor_id(this), dialog_id, message_id, file_id, thumbnail_file_id, schedule_date, generation = m->edit_generation, was_uploaded, was_thumbnail_uploaded, - file_reference = FileManager::extract_file_reference(input_media)](Result result) mutable { + file_reference = FileManager::extract_file_reference(input_media)](Result result) mutable { send_closure(actor_id, &MessagesManager::on_message_media_edited, dialog_id, message_id, file_id, thumbnail_file_id, was_uploaded, was_thumbnail_uploaded, std::move(file_reference), schedule_date, generation, std::move(result)); @@ -24412,7 +24424,7 @@ void MessagesManager::cancel_edit_message_media(DialogId dialog_id, Message *m, void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id, bool was_uploaded, bool was_thumbnail_uploaded, string file_reference, int32 schedule_date, uint64 generation, - Result &&result) { + Result &&result) { // must not run getDifference CHECK(message_id.is_any_server()); @@ -24425,15 +24437,20 @@ void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId mess CHECK(m->edited_content != nullptr); if (result.is_ok()) { // message content has already been replaced from updateEdit{Channel,}Message - // TODO check that it really was replaced // need only merge files from edited_content with their uploaded counterparts // updateMessageContent was already sent and needs to be sent again, // only if 'i' and 't' sizes from edited_content was added to the photo + auto pts = result.ok(); + LOG(INFO) << "Successfully edited " << message_id << " in " << dialog_id << " with pts = " << pts + << " and last edit pts = " << m->last_edit_pts; std::swap(m->content, m->edited_content); bool need_send_update_message_content = m->edited_content->get_type() == MessageContentType::Photo && m->content->get_type() == MessageContentType::Photo; - update_message_content(dialog_id, m, std::move(m->edited_content), need_send_update_message_content, true, true); + bool need_merge_files = pts != 0 && pts == m->last_edit_pts; + update_message_content(dialog_id, m, std::move(m->edited_content), need_send_update_message_content, + need_merge_files, true); } else { + LOG(INFO) << "Failed to edit " << message_id << " in " << dialog_id << ": " << result.error(); if (was_uploaded) { if (was_thumbnail_uploaded) { CHECK(thumbnail_file_id.is_valid()); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index bded8144d..508061ba1 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1811,7 +1811,7 @@ class MessagesManager : public Actor { void on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id, bool was_uploaded, bool was_thumbnail_uploaded, string file_reference, - int32 scheduled_date, uint64 generation, Result &&result); + int32 scheduled_date, uint64 generation, Result &&result); MessageId get_persistent_message_id(const Dialog *d, MessageId message_id) const; diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index b8bdbd003..536ae1a6f 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1008,6 +1008,37 @@ vector UpdatesManager::get_chat_dialog_ids(const telegram_api::Updates return dialog_ids; } +int32 UpdatesManager::get_update_edit_message_pts(const telegram_api::Updates *updates_ptr) { + int32 pts = 0; + auto updates = get_updates(updates_ptr); + if (updates != nullptr) { + for (auto &update : *updates) { + int32 update_pts = [&] { + switch (update->get_id()) { + case telegram_api::updateEditMessage::ID: + return static_cast(update.get())->pts_; + case telegram_api::updateEditChannelMessage::ID: + return static_cast(update.get())->pts_; + default: + return 0; + } + }(); + if (update_pts != 0) { + if (pts == 0) { + pts = update_pts; + } else { + pts = -1; + } + } + } + } + if (pts == -1) { + LOG(ERROR) << "Receive multiple edit message updates in " << to_string(*updates_ptr); + pts = 0; + } + return pts; +} + void UpdatesManager::init_state() { if (!td_->auth_manager_->is_authorized()) { return; diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index c98a6737f..92f5a2cea 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -51,6 +51,8 @@ class UpdatesManager : public Actor { static vector get_chat_dialog_ids(const telegram_api::Updates *updates_ptr); + static int32 get_update_edit_message_pts(const telegram_api::Updates *updates_ptr); + void get_difference(const char *source); void schedule_get_difference(const char *source); From ce75097932c5529e9d534bd14076807d2ed187da Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 17:35:41 +0300 Subject: [PATCH 11/31] Increase ChannelFull.participant_count instead of decreasing administrator_count to guarantee that channel has no administrators more than participants. --- td/telegram/ContactsManager.cpp | 48 ++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index e83f31856..94069a9f7 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8706,6 +8706,18 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s auto photo = std::move(channel_full->photo); on_update_channel_full_photo(channel_full, channel_id, std::move(photo)); + if (channel_full->participant_count < channel_full->administrator_count) { + channel_full->participant_count = channel_full->administrator_count; + } + if (c->participant_count != channel_full->participant_count) { + channel_full->participant_count = c->participant_count; + + if (channel_full->participant_count < channel_full->administrator_count) { + channel_full->participant_count = channel_full->administrator_count; + channel_full->expires_at = 0.0; + } + } + update_channel_full(channel_full, channel_id, true); if (channel_full->expires_at == 0.0) { @@ -9110,9 +9122,7 @@ void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId c CHECK(channel_full != nullptr); unavailable_channel_fulls_.erase(channel_id); // don't needed anymore - if (channel_full->participant_count < channel_full->administrator_count) { - channel_full->administrator_count = channel_full->participant_count; - } + CHECK(channel_full->participant_count >= channel_full->administrator_count); if (channel_full->is_slow_mode_next_send_date_changed) { auto now = G()->server_time(); @@ -9517,14 +9527,17 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c ChannelFull *channel = add_channel_full(channel_id); bool have_participant_count = (channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT) != 0; - auto participant_count = have_participant_count ? channel_full->participants_count_ : 0; + auto participant_count = have_participant_count ? channel_full->participants_count_ : channel->participant_count; auto administrator_count = 0; if ((channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT) != 0) { administrator_count = channel_full->admins_count_; } else if (c->is_megagroup || c->status.is_administrator()) { - // in megagroups and administrated channels don't drop known number of administrators + // in megagroups and administered channels don't drop known number of administrators administrator_count = channel->administrator_count; } + if (participant_count < administrator_count) { + participant_count = administrator_count; + } auto restricted_count = (channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_BANNED_COUNT) != 0 ? channel_full->banned_count_ : 0; auto banned_count = @@ -10695,11 +10708,20 @@ void ContactsManager::on_get_channel_participants_success( if (participant_count != -1 || administrator_count != -1) { auto channel_full = get_channel_full_force(channel_id, "on_get_channel_participants_success"); if (channel_full != nullptr) { - if (participant_count != -1 && channel_full->participant_count != participant_count) { + if (administrator_count == -1) { + administrator_count = channel_full->administrator_count; + } + if (participant_count == -1) { + participant_count = channel_full->participant_count; + } + if (participant_count < administrator_count) { + participant_count = administrator_count; + } + if (channel_full->participant_count != participant_count) { channel_full->participant_count = participant_count; channel_full->is_changed = true; } - if (administrator_count != -1 && channel_full->administrator_count != administrator_count) { + if (channel_full->administrator_count != administrator_count) { channel_full->administrator_count = administrator_count; channel_full->is_changed = true; } @@ -13660,6 +13682,18 @@ void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id if (channel_full != nullptr && channel_full->administrator_count != administrator_count) { channel_full->administrator_count = administrator_count; channel_full->is_changed = true; + + if (channel_full->participant_count < channel_full->administrator_count) { + channel_full->participant_count = channel_full->administrator_count; + + auto c = get_channel(channel_id); + if (c != nullptr && c->participant_count != channel_full->participant_count) { + c->participant_count = channel_full->participant_count; + c->is_changed = true; + update_channel(c, channel_id); + } + } + update_channel_full(channel_full, channel_id); } } From c8668f224c30ff754b8b5eac6cb9d42a9248c8b3 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 25 Dec 2020 18:06:54 +0300 Subject: [PATCH 12/31] Update ChannelFull.participant_count when channel.participant_count changes. --- td/telegram/ContactsManager.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 94069a9f7..04a64050d 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -13919,6 +13919,13 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char int32 participant_count = (channel.flags_ & CHANNEL_FLAG_HAS_PARTICIPANT_COUNT) != 0 ? channel.participants_count_ : 0; + if (participant_count != 0) { + auto channel_full = get_channel_full_const(channel_id); + if (channel_full != nullptr && channel_full->administrator_count > participant_count) { + participant_count = channel_full->administrator_count; + } + } + { bool is_broadcast = (channel.flags_ & CHANNEL_FLAG_IS_BROADCAST) != 0; LOG_IF(ERROR, is_broadcast == is_megagroup) @@ -14010,6 +14017,13 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char if (participant_count != 0 && participant_count != c->participant_count) { c->participant_count = participant_count; c->is_changed = true; + + auto channel_full = get_channel_full(channel_id, "on_chat_update"); + if (channel_full != nullptr && channel_full->participant_count != participant_count) { + channel_full->participant_count = participant_count; + channel_full->is_changed = true; + update_channel_full(channel_full, channel_id); + } } bool need_invalidate_channel_full = false; @@ -14105,11 +14119,6 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co sign_messages = true; } - if (c->participant_count != 0) { - c->participant_count = 0; - c->is_changed = true; - } - bool need_invalidate_channel_full = false; if (c->is_slow_mode_enabled != is_slow_mode_enabled || c->is_megagroup != is_megagroup || !c->restriction_reasons.empty() || c->is_scam != is_scam) { @@ -14130,6 +14139,19 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co c->is_changed = true; } + if (c->participant_count != 0) { + c->participant_count = 0; + c->is_changed = true; + + auto channel_full = get_channel_full(channel_id, "on_chat_update"); + if (channel_full != nullptr && channel_full->participant_count != 0) { + channel_full->participant_count = 0; + channel_full->administrator_count = 0; + channel_full->is_changed = true; + update_channel_full(channel_full, channel_id); + } + } + if (c->cache_version != Channel::CACHE_VERSION) { c->cache_version = Channel::CACHE_VERSION; c->need_save_to_database = true; From f4ec6e6cfcd681bac760a9ecdf3a40eafccb2004 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 00:43:38 +0300 Subject: [PATCH 13/31] tg_cli: add get_search_query. --- td/telegram/cli.cpp | 135 +++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 72 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index eaf032779..514372d59 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef USE_READLINE /* Standard readline include files. */ @@ -657,6 +658,18 @@ class CliClient final : public Actor { return transform(transform(full_split(ids_string, get_delimiter(ids_string)), trim), to_integer); } + static std::pair get_search_query(string args) { + string limit; + string query; + std::tie(limit, query) = split(trim(args)); + auto r_limit = to_integer_safe(limit); + if (r_limit.is_error() || r_limit.ok() <= 0) { + query = limit + ' ' + query; + r_limit = 10; + } + return {r_limit.ok(), std::move(query)}; + } + void on_result(uint64 generation, uint64 id, td_api::object_ptr result) { auto result_str = to_string(result); if (result != nullptr) { @@ -1843,7 +1856,7 @@ class CliClient final : public Actor { string thread_message_id; string from_message_id; string offset; - string limit; + int32 limit; std::tie(chat_id, args) = split(args); if (op == "gmth") { @@ -1857,20 +1870,16 @@ class CliClient final : public Actor { if (offset.empty()) { offset = "0"; } - std::tie(limit, args) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, args) = get_search_query(args); if (!args.empty()) { LOG(ERROR) << "Wrong parameters to function getChatHistory specified"; } else if (op == "gmth") { send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id), - to_integer(offset), to_integer(limit))); + to_integer(offset), limit)); } else { send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(from_message_id), - to_integer(offset), to_integer(limit), - op == "ghl")); + to_integer(offset), limit, op == "ghl")); } } else if (op == "gcsm") { string chat_id = args; @@ -1929,17 +1938,14 @@ class CliClient final : public Actor { as_search_messages_filter(filter), 1, 2147483647)); } else if (op == "SCM") { string chat_id; - string limit; + int32 limit; string query; std::tie(chat_id, args) = split(args); - std::tie(limit, query) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, nullptr, 0, 0, - to_integer(limit), nullptr, 0)); + send_request(td_api::make_object(as_chat_id(chat_id), query, nullptr, 0, 0, limit, + nullptr, 0)); } else if (op == "SMME") { string chat_id; string limit; @@ -2019,7 +2025,7 @@ class CliClient final : public Actor { } else if (op == "SearchAudio") { string chat_id; string offset_message_id; - string limit; + int32 limit; string query; std::tie(chat_id, args) = split(args); @@ -2027,17 +2033,14 @@ class CliClient final : public Actor { if (offset_message_id.empty()) { offset_message_id = "0"; } - std::tie(limit, query) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer(limit), + as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, td_api::make_object(), 0)); } else if (op == "SearchDocument") { string chat_id; string offset_message_id; - string limit; + int32 limit; string query; std::tie(chat_id, args) = split(args); @@ -2045,17 +2048,14 @@ class CliClient final : public Actor { if (offset_message_id.empty()) { offset_message_id = "0"; } - std::tie(limit, query) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, to_integer(offset_message_id), 0, to_integer(limit), + as_chat_id(chat_id), query, nullptr, to_integer(offset_message_id), 0, limit, td_api::make_object(), 0)); } else if (op == "SearchPhoto") { string chat_id; string offset_message_id; - string limit; + int32 limit; string query; std::tie(chat_id, args) = split(args); @@ -2063,17 +2063,14 @@ class CliClient final : public Actor { if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } - std::tie(limit, query) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer(limit), + as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, td_api::make_object(), 0)); } else if (op == "SearchChatPhoto") { string chat_id; string offset_message_id; - string limit; + int32 limit; string query; std::tie(chat_id, args) = split(args); @@ -2081,12 +2078,9 @@ class CliClient final : public Actor { if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } - std::tie(limit, query) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer(limit), + as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, td_api::make_object(), 0)); } else if (op == "gcmc") { string chat_id; @@ -2101,22 +2095,19 @@ class CliClient final : public Actor { } else if (op == "gup" || op == "gupp") { string user_id; string offset; - string limit; + int32 limit; std::tie(user_id, args) = split(args); std::tie(offset, args) = split(args); if (offset.empty()) { offset = "0"; } - std::tie(limit, args) = split(args); - if (limit.empty()) { - limit = "10"; - } + std::tie(limit, args) = get_search_query(args); if (!args.empty()) { LOG(ERROR) << "Wrong parameters to function getUserProfilePhotos specified"; } else { - send_request(td_api::make_object(as_user_id(user_id), to_integer(offset), - to_integer(limit))); + send_request( + td_api::make_object(as_user_id(user_id), to_integer(offset), limit)); } } else if (op == "dcrm") { string chat_id; @@ -2341,15 +2332,15 @@ class CliClient final : public Actor { } else if (op == "gsu") { send_request(td_api::make_object()); } else if (op == "gs") { - string limit; + int32 limit; string emoji; - std::tie(limit, emoji) = split(args); - send_request(td_api::make_object(emoji, to_integer(limit))); + std::tie(limit, emoji) = get_search_query(args); + send_request(td_api::make_object(emoji, limit)); } else if (op == "sst") { - string limit; + int32 limit; string emoji; - std::tie(limit, emoji) = split(args); - send_request(td_api::make_object(emoji, to_integer(limit))); + std::tie(limit, emoji) = get_search_query(args); + send_request(td_api::make_object(emoji, limit)); } else if (op == "gss") { send_request(td_api::make_object(to_integer(args))); } else if (op == "giss") { @@ -2544,14 +2535,14 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_secret_chat_id(args))); } else if (op == "scm") { string chat_id; - string limit; - string query; string filter; + int32 limit; + string query; std::tie(chat_id, args) = split(args); - std::tie(limit, args) = split(args); - std::tie(query, filter) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, to_integer(limit), + std::tie(filter, args) = split(args); + std::tie(limit, query) = get_search_query(args); + send_request(td_api::make_object(as_chat_id(chat_id), query, limit, get_chat_members_filter(filter))); } else if (op == "gcm") { string chat_id; @@ -3062,18 +3053,18 @@ class CliClient final : public Actor { } } else if (op == "ssm") { string chat_id; - string offset; - string limit; string filter; + string offset; + int32 limit; string query; std::tie(chat_id, args) = split(args); + std::tie(filter, args) = split(args); std::tie(offset, args) = split(args); - std::tie(limit, args) = split(args); - std::tie(filter, query) = split(args); + std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object( - as_chat_id(chat_id), query, offset, to_integer(limit), as_search_messages_filter(filter))); + send_request(td_api::make_object(as_chat_id(chat_id), query, offset, limit, + as_search_messages_filter(filter))); } else if (op == "ssd") { schedule_date_ = args; } else if (op == "smti") { @@ -4052,15 +4043,15 @@ class CliClient final : public Actor { } else if (op == "spcs") { send_request(td_api::make_object(args)); } else if (op == "sc") { - string limit; + int32 limit; string query; - std::tie(limit, query) = split(args); - send_request(td_api::make_object(query, to_integer(limit))); + std::tie(limit, query) = get_search_query(args); + send_request(td_api::make_object(query, limit)); } else if (op == "scos") { - string limit; + int32 limit; string query; - std::tie(limit, query) = split(args); - send_request(td_api::make_object(query, to_integer(limit))); + std::tie(limit, query) = get_search_query(args); + send_request(td_api::make_object(query, limit)); } else if (op == "scn") { string latitude; string longitude; @@ -4074,10 +4065,10 @@ class CliClient final : public Actor { std::tie(latitude, longitude) = split(args); send_request(td_api::make_object(as_location(latitude, longitude))); } else if (op == "sco") { - string limit; + int32 limit; string query; - std::tie(limit, query) = split(args); - send_request(td_api::make_object(query, to_integer(limit))); + std::tie(limit, query) = get_search_query(args); + send_request(td_api::make_object(query, limit)); } else if (op == "arfc") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "rrfc") { From 30d912bd4b145afb8d494b307d37645ffa21ec29 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 01:05:24 +0300 Subject: [PATCH 14/31] Set is_pinned flag for last_pinned_message_id. --- td/telegram/MessagesManager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c5611499e..7a57c2762 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -28776,6 +28776,10 @@ void MessagesManager::on_update_dialog_last_pinned_message_id(DialogId dialog_id d->is_last_pinned_message_id_inited = true; on_dialog_updated(dialog_id, "on_update_dialog_last_pinned_message_id"); } + Message *m = get_message_force(d, pinned_message_id, "on_update_dialog_last_pinned_message_id"); + if (m != nullptr && update_message_is_pinned(d, m, true, "on_update_dialog_last_pinned_message_id")) { + on_message_changed(d, m, true, "on_update_dialog_last_pinned_message_id"); + } return; } @@ -28784,6 +28788,11 @@ void MessagesManager::on_update_dialog_last_pinned_message_id(DialogId dialog_id void MessagesManager::set_dialog_last_pinned_message_id(Dialog *d, MessageId pinned_message_id) { CHECK(d != nullptr); + Message *m = get_message_force(d, pinned_message_id, "set_dialog_last_pinned_message_id"); + if (m != nullptr && update_message_is_pinned(d, m, true, "set_dialog_last_pinned_message_id")) { + on_message_changed(d, m, true, "set_dialog_last_pinned_message_id"); + } + if (d->last_pinned_message_id == pinned_message_id) { return; } From 77112f53d7935b3f1aa71a827952a59285745cb5 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 01:25:00 +0300 Subject: [PATCH 15/31] tg_cli: add as_limit. --- td/telegram/cli.cpp | 89 ++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 58 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 514372d59..7f0506bc4 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -524,6 +524,13 @@ class CliClient final : public Actor { return to_integer(trim(str)); } + static int32 as_limit(Slice str, int32 default_limit = 10) { + if (str.empty()) { + return default_limit; + } + return to_integer(trim(str)); + } + int32 as_user_id(Slice str) const { str = trim(str); if (str[0] == '@') { @@ -1772,8 +1779,7 @@ class CliClient final : public Actor { if (args.empty()) { send_request(td_api::make_object()); } else { - auto limit = to_integer(args); - send_request(td_api::make_object("", limit)); + send_request(td_api::make_object("", as_limit(args))); } } else if (op == "AddContact") { string user_id; @@ -1823,9 +1829,6 @@ class CliClient final : public Actor { std::tie(limit, args) = split(args); std::tie(offset_order_string, offset_chat_id) = split(args); - if (limit.empty()) { - limit = "10000"; - } int64 offset_order; if (offset_order_string.empty()) { offset_order = std::numeric_limits::max(); @@ -1833,7 +1836,7 @@ class CliClient final : public Actor { offset_order = to_integer(offset_order_string); } send_request(td_api::make_object(as_chat_list(op), offset_order, as_chat_id(offset_chat_id), - to_integer(limit))); + as_limit(limit, 10000))); } else if (op == "gctest") { send_request(td_api::make_object(nullptr, std::numeric_limits::max(), 0, 1)); send_request(td_api::make_object(nullptr, std::numeric_limits::max(), 0, 10)); @@ -1846,11 +1849,8 @@ class CliClient final : public Actor { std::tie(user_id, args) = split(args); std::tie(offset_chat_id, limit) = split(args); - if (limit.empty()) { - limit = "100"; - } send_request(td_api::make_object(as_user_id(user_id), as_chat_id(offset_chat_id), - to_integer(limit))); + as_limit(limit, 100))); } else if (op == "gh" || op == "GetHistory" || op == "ghl" || op == "gmth") { string chat_id; string thread_message_id; @@ -1895,7 +1895,7 @@ class CliClient final : public Actor { std::tie(offset, limit) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - offset, to_integer(limit))); + offset, as_limit(limit))); } else if (op == "ghf") { get_history_chat_id_ = as_chat_id(args); @@ -1934,7 +1934,7 @@ class CliClient final : public Actor { chat_list = td_api::make_object(); } send_request(td_api::make_object( - std::move(chat_list), query, to_integer(from_date), 2147483647, 0, to_integer(limit), + std::move(chat_list), query, to_integer(from_date), 2147483647, 0, as_limit(limit), as_search_messages_filter(filter), 1, 2147483647)); } else if (op == "SCM") { string chat_id; @@ -1951,13 +1951,10 @@ class CliClient final : public Actor { string limit; std::tie(chat_id, limit) = split(args); - if (limit.empty()) { - limit = "10"; - } send_request(td_api::make_object( - as_chat_id(chat_id), "", td_api::make_object(my_id_), 0, 0, - to_integer(limit), nullptr, 0)); + as_chat_id(chat_id), "", td_api::make_object(my_id_), 0, 0, as_limit(limit), + nullptr, 0)); } else if (op == "SMU" || op == "SMC") { string chat_id; string sender_id; @@ -1965,12 +1962,9 @@ class CliClient final : public Actor { std::tie(chat_id, args) = split(args); std::tie(sender_id, limit) = split(args); - if (limit.empty()) { - limit = "10"; - } send_request(td_api::make_object( - as_chat_id(chat_id), "", as_message_sender(sender_id), 0, 0, to_integer(limit), nullptr, 0)); + as_chat_id(chat_id), "", as_message_sender(sender_id), 0, 0, as_limit(limit), nullptr, 0)); } else if (op == "SM") { string chat_id; string filter; @@ -1982,9 +1976,6 @@ class CliClient final : public Actor { std::tie(filter, args) = split(args); std::tie(limit, args) = split(args); std::tie(offset_message_id, offset) = split(args); - if (limit.empty()) { - limit = "10"; - } if (offset_message_id.empty()) { offset_message_id = "0"; } @@ -1994,7 +1985,7 @@ class CliClient final : public Actor { send_request(td_api::make_object( as_chat_id(chat_id), "", nullptr, as_message_id(offset_message_id), to_integer(offset), - to_integer(limit), as_search_messages_filter(filter), 0)); + as_limit(limit), as_search_messages_filter(filter), 0)); } else if (op == "SC") { string limit; string offset_message_id; @@ -2002,26 +1993,19 @@ class CliClient final : public Actor { std::tie(limit, args) = split(args); std::tie(offset_message_id, only_missed) = split(args); - if (limit.empty()) { - limit = "10"; - } if (offset_message_id.empty()) { offset_message_id = "0"; } - send_request(td_api::make_object(as_message_id(offset_message_id), - to_integer(limit), as_bool(only_missed))); + send_request(td_api::make_object(as_message_id(offset_message_id), as_limit(limit), + as_bool(only_missed))); } else if (op == "SCRLM") { string chat_id; string limit; std::tie(chat_id, limit) = split(args); - if (limit.empty()) { - limit = "10"; - } - send_request( - td_api::make_object(as_chat_id(chat_id), to_integer(limit))); + send_request(td_api::make_object(as_chat_id(chat_id), as_limit(limit))); } else if (op == "SearchAudio") { string chat_id; string offset_message_id; @@ -2322,11 +2306,7 @@ class CliClient final : public Actor { if (offset.empty()) { offset = "0"; } - if (limit.empty()) { - limit = "10"; - } - send_request( - td_api::make_object(to_integer(offset), to_integer(limit))); + send_request(td_api::make_object(to_integer(offset), as_limit(limit))); } else if (op == "gu") { send_request(td_api::make_object(as_user_id(args))); } else if (op == "gsu") { @@ -2354,22 +2334,18 @@ class CliClient final : public Actor { std::tie(offset_sticker_set_id, limit) = split(args); send_request(td_api::make_object( - as_bool(is_masks), to_integer(offset_sticker_set_id), to_integer(limit))); + as_bool(is_masks), to_integer(offset_sticker_set_id), as_limit(limit))); } else if (op == "gtss") { string offset; string limit; std::tie(offset, limit) = split(args); - if (limit.empty()) { - limit = "1000"; - } send_request( - td_api::make_object(to_integer(offset), to_integer(limit))); + td_api::make_object(to_integer(offset), as_limit(limit, 1000))); } else if (op == "gatss") { send_request(td_api::make_object(as_file_id(args))); } else if (op == "storage") { - auto chat_limit = to_integer(args); - send_request(td_api::make_object(chat_limit)); + send_request(td_api::make_object(as_limit(args))); } else if (op == "storage_fast") { send_request(td_api::make_object()); } else if (op == "database") { @@ -2574,9 +2550,6 @@ class CliClient final : public Actor { if (offset.empty()) { offset = "0"; } - if (limit.empty()) { - limit = "10"; - } td_api::object_ptr filter; if (op == "GetSupergroupAdministrators") { filter = td_api::make_object(); @@ -2596,8 +2569,8 @@ class CliClient final : public Actor { filter = td_api::make_object(query, as_message_thread_id(message_thread_id)); } - send_request(td_api::make_object( - as_supergroup_id(supergroup_id), std::move(filter), to_integer(offset), to_integer(limit))); + send_request(td_api::make_object(as_supergroup_id(supergroup_id), std::move(filter), + to_integer(offset), as_limit(limit))); } else if (op == "gdialog" || op == "gd") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "open") { @@ -2720,7 +2693,7 @@ class CliClient final : public Actor { int32 min_file_id = (op == "dff" ? 1 : max_file_id); for (int32 i = min_file_id; i <= max_file_id; i++) { send_request(td_api::make_object( - i, to_integer(priority), to_integer(offset), to_integer(limit), op == "dfs")); + i, to_integer(priority), to_integer(offset), as_limit(limit), op == "dfs")); } } else if (op == "cdf") { send_request(td_api::make_object(as_file_id(args), false)); @@ -2871,8 +2844,8 @@ class CliClient final : public Actor { string group_call_id; string limit; std::tie(group_call_id, limit) = split(args); - send_request(td_api::make_object(as_group_call_id(group_call_id), - to_integer(limit))); + send_request( + td_api::make_object(as_group_call_id(group_call_id), as_limit(limit))); } else if (op == "lgc") { send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "dgc") { @@ -3838,7 +3811,7 @@ class CliClient final : public Actor { std::tie(offset, limit) = split(args); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), to_integer(option_id), to_integer(offset), - to_integer(limit))); + as_limit(limit))); } else if (op == "stoppoll") { string chat_id; string message_id; @@ -3933,8 +3906,8 @@ class CliClient final : public Actor { string limit; std::tie(chat_id, limit) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), "", 0, to_integer(limit), - nullptr, vector())); + send_request(td_api::make_object(as_chat_id(chat_id), "", 0, as_limit(limit), nullptr, + vector())); } else if (op == "join") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "leave") { From 48a47618caff1858f3295cb99326b5a0cf257595 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 19:40:46 +0300 Subject: [PATCH 16/31] tg_cli: add get_args. --- td/telegram/cli.cpp | 753 ++++++++++++++------------------------------ 1 file changed, 242 insertions(+), 511 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 7f0506bc4..c5cfeccb7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -665,6 +665,29 @@ class CliClient final : public Actor { return transform(transform(full_split(ids_string, get_delimiter(ids_string)), trim), to_integer); } + void get_args(string &args, string &arg) { + if (&args != &arg) { + arg = std::move(args); + } + } + + void get_args(string &args, bool &arg) { + arg = as_bool(args); + } + + template + void get_args(string &args, Type &arg) { + arg = to_integer(args); + } + + template + void get_args(string &args, FirstType &first_arg, SecondType &second_arg, Types &... other_args) { + string arg; + std::tie(arg, args) = split(args); + get_args(arg, first_arg); + get_args(args, second_arg, other_args...); + } + static std::pair get_search_query(string args) { string limit; string query; @@ -1476,9 +1499,7 @@ class CliClient final : public Actor { } else if (op == "ru") { string first_name; string last_name; - - std::tie(first_name, last_name) = split(args); - + get_args(args, first_name, last_name); send_request(td_api::make_object(first_name, last_name)); } else if (op == "cap") { send_request(td_api::make_object(args)); @@ -1514,19 +1535,16 @@ class CliClient final : public Actor { string new_password; string new_hint; string recovery_email_address; - std::tie(password, args) = split(args); + get_args(args, password, new_password, new_hint, recovery_email_address); if (password == "#") { password = ""; } - std::tie(new_password, args) = split(args); if (new_password == "#") { new_password = ""; } - std::tie(new_hint, args) = split(args); if (new_hint == "#") { new_hint = ""; } - recovery_email_address = args; if (recovery_email_address == "#") { recovery_email_address = ""; } @@ -1570,21 +1588,19 @@ class CliClient final : public Actor { "P7d2+fuJMlkjtM7oAwf+tI8CAwEAAQ==\n" "-----END PUBLIC KEY-----"; string payload; - - std::tie(bot_id, args) = split(args); - std::tie(scope, payload) = split(args); + get_args(args, bot_id, scope, payload); send_request( td_api::make_object(as_user_id(bot_id), scope, public_key, payload)); } else if (op == "gpafae") { string form_id; string password; - std::tie(form_id, password) = split(args); + get_args(args, form_id, password); send_request(td_api::make_object( to_integer(form_id), password)); } else if (op == "spaf") { string form_id; string types; - std::tie(form_id, types) = split(args); + get_args(args, form_id, types); send_request(td_api::make_object(to_integer(form_id), as_passport_element_types(types))); } else if (op == "gpcl") { @@ -1604,7 +1620,7 @@ class CliClient final : public Actor { } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address; - std::tie(password, recovery_email_address) = split(args); + get_args(args, password, recovery_email_address); send_request(td_api::make_object(password, recovery_email_address)); } else if (op == "grea" || op == "GetRecoveryEmailAddress") { send_request(td_api::make_object(args)); @@ -1629,7 +1645,7 @@ class CliClient final : public Actor { } else if (op == "gpe") { string password; string passport_element_type; - std::tie(password, passport_element_type) = split(args); + get_args(args, password, passport_element_type); send_request( td_api::make_object(as_passport_element_type(passport_element_type), password)); } else if (op == "gape") { @@ -1639,8 +1655,7 @@ class CliClient final : public Actor { string password; string passport_element_type; string arg; - std::tie(password, args) = split(args); - std::tie(passport_element_type, arg) = split(args); + get_args(args, password, passport_element_type, arg); send_request(td_api::make_object( as_input_passport_element(passport_element_type, arg, op == "spes"), password)); } else if (op == "dpe") { @@ -1662,15 +1677,13 @@ class CliClient final : public Actor { } else if (op == "rdt") { string token; string other_user_ids_str; - - std::tie(token, other_user_ids_str) = split(args); + get_args(args, token, other_user_ids_str); send_request(td_api::make_object(td_api::make_object(token), as_user_ids(other_user_ids_str))); } else if (op == "rdu") { string token; string other_user_ids_str; - - std::tie(token, other_user_ids_str) = split(args); + get_args(args, token, other_user_ids_str); send_request(td_api::make_object( td_api::make_object(token), as_user_ids(other_user_ids_str))); } else if (op == "rdw") { @@ -1679,9 +1692,7 @@ class CliClient final : public Actor { string secret; string other_user_ids_str; - std::tie(endpoint, args) = split(args); - std::tie(key, args) = split(args); - std::tie(secret, other_user_ids_str) = split(args); + get_args(args, endpoint, key, secret, other_user_ids_str); send_request(td_api::make_object( td_api::make_object(endpoint, key, secret), as_user_ids(other_user_ids_str))); } else if (op == "gbci") { @@ -1690,15 +1701,14 @@ class CliClient final : public Actor { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "voi") { string chat_id; string message_id; string allow_save; - std::tie(chat_id, args) = split(args); - std::tie(message_id, allow_save) = split(args); + get_args(args, chat_id, message_id, allow_save); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), nullptr, as_bool(allow_save))); } else if (op == "spfs") { @@ -1707,11 +1717,7 @@ class CliClient final : public Actor { string order_info_id; string shipping_option_id; string saved_credentials_id; - - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(order_info_id, args) = split(args); - std::tie(shipping_option_id, saved_credentials_id) = split(args); + get_args(args, chat_id, message_id, order_info_id, shipping_option_id, saved_credentials_id); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), order_info_id, shipping_option_id, td_api::make_object(saved_credentials_id))); @@ -1721,19 +1727,14 @@ class CliClient final : public Actor { string order_info_id; string shipping_option_id; string data; - - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(order_info_id, args) = split(args); - std::tie(shipping_option_id, data) = split(args); + get_args(args, chat_id, message_id, order_info_id, shipping_option_id, data); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), order_info_id, shipping_option_id, td_api::make_object(data, true))); } else if (op == "gpre") { string chat_id; string message_id; - - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "gsoi") { send_request(td_api::make_object()); @@ -1751,8 +1752,7 @@ class CliClient final : public Actor { string setting; string allow; string ids; - std::tie(setting, args) = split(args); - std::tie(allow, ids) = split(args); + get_args(args, setting, allow, ids); std::vector> rules; if (allow == "c" || allow == "contacts") { @@ -1785,8 +1785,7 @@ class CliClient final : public Actor { string user_id; string first_name; string last_name; - std::tie(user_id, args) = split(args); - std::tie(first_name, last_name) = split(args); + get_args(args, user_id, first_name, last_name); send_request(td_api::make_object( td_api::make_object(string(), first_name, last_name, string(), as_user_id(user_id)), false)); @@ -1825,9 +1824,7 @@ class CliClient final : public Actor { string limit; string offset_order_string; string offset_chat_id; - - std::tie(limit, args) = split(args); - std::tie(offset_order_string, offset_chat_id) = split(args); + get_args(args, limit, offset_order_string, offset_chat_id); int64 offset_order; if (offset_order_string.empty()) { @@ -1845,10 +1842,7 @@ class CliClient final : public Actor { string user_id; string offset_chat_id; string limit; - - std::tie(user_id, args) = split(args); - std::tie(offset_chat_id, limit) = split(args); - + get_args(args, user_id, offset_chat_id, limit); send_request(td_api::make_object(as_user_id(user_id), as_chat_id(offset_chat_id), as_limit(limit, 100))); } else if (op == "gh" || op == "GetHistory" || op == "ghl" || op == "gmth") { @@ -1857,7 +1851,6 @@ class CliClient final : public Actor { string from_message_id; string offset; int32 limit; - std::tie(chat_id, args) = split(args); if (op == "gmth") { std::tie(thread_message_id, args) = split(args); @@ -1889,43 +1882,30 @@ class CliClient final : public Actor { string message_id; string offset; string limit; - - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(offset, limit) = split(args); - + get_args(args, chat_id, message_id, offset, limit); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), offset, as_limit(limit))); } else if (op == "ghf") { get_history_chat_id_ = as_chat_id(args); - send_request(td_api::make_object(get_history_chat_id_, std::numeric_limits::max(), 0, 100, false)); } else if (op == "replies") { string chat_id; string message_thread_id; - - std::tie(chat_id, message_thread_id) = split(args); + get_args(args, chat_id, message_thread_id); send_request(td_api::make_object(as_chat_id(chat_id), "", nullptr, 0, 0, 100, nullptr, as_message_thread_id(message_thread_id))); } else if (op == "spvf") { search_chat_id_ = as_chat_id(args); - send_request(td_api::make_object( search_chat_id_, "", nullptr, 0, 0, 100, td_api::make_object(), 0)); } else if (op == "Search" || op == "SearchA" || op == "SearchM") { - string from_date; - string limit; string query; + string limit; string filter; - - std::tie(query, args) = split(args); - std::tie(limit, args) = split(args); - std::tie(filter, from_date) = split(args); - if (from_date.empty()) { - from_date = "0"; - } + int32 from_date; + get_args(args, query, limit, filter, from_date); td_api::object_ptr chat_list; if (op == "SearchA") { chat_list = td_api::make_object(); @@ -1933,25 +1913,21 @@ class CliClient final : public Actor { if (op == "SearchM") { chat_list = td_api::make_object(); } - send_request(td_api::make_object( - std::move(chat_list), query, to_integer(from_date), 2147483647, 0, as_limit(limit), - as_search_messages_filter(filter), 1, 2147483647)); + send_request(td_api::make_object(std::move(chat_list), query, from_date, 2147483647, 0, + as_limit(limit), as_search_messages_filter(filter), 1, + 2147483647)); } else if (op == "SCM") { string chat_id; int32 limit; string query; - - std::tie(chat_id, args) = split(args); + get_args(args, chat_id, args); std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, nullptr, 0, 0, limit, nullptr, 0)); } else if (op == "SMME") { string chat_id; string limit; - - std::tie(chat_id, limit) = split(args); - + get_args(args, chat_id, limit); send_request(td_api::make_object( as_chat_id(chat_id), "", td_api::make_object(my_id_), 0, 0, as_limit(limit), nullptr, 0)); @@ -1959,10 +1935,7 @@ class CliClient final : public Actor { string chat_id; string sender_id; string limit; - - std::tie(chat_id, args) = split(args); - std::tie(sender_id, limit) = split(args); - + get_args(args, chat_id, sender_id, limit); send_request(td_api::make_object( as_chat_id(chat_id), "", as_message_sender(sender_id), 0, 0, as_limit(limit), nullptr, 0)); } else if (op == "SM") { @@ -1972,10 +1945,7 @@ class CliClient final : public Actor { string offset_message_id; string offset; - std::tie(chat_id, args) = split(args); - std::tie(filter, args) = split(args); - std::tie(limit, args) = split(args); - std::tie(offset_message_id, offset) = split(args); + get_args(args, chat_id, filter, limit, offset_message_id, offset); if (offset_message_id.empty()) { offset_message_id = "0"; } @@ -1991,8 +1961,7 @@ class CliClient final : public Actor { string offset_message_id; string only_missed; - std::tie(limit, args) = split(args); - std::tie(offset_message_id, only_missed) = split(args); + get_args(args, limit, offset_message_id, only_missed); if (offset_message_id.empty()) { offset_message_id = "0"; } @@ -2002,18 +1971,14 @@ class CliClient final : public Actor { } else if (op == "SCRLM") { string chat_id; string limit; - - std::tie(chat_id, limit) = split(args); - + get_args(args, chat_id, limit); send_request(td_api::make_object(as_chat_id(chat_id), as_limit(limit))); } else if (op == "SearchAudio") { string chat_id; string offset_message_id; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(offset_message_id, args) = split(args); + get_args(args, chat_id, offset_message_id, args); if (offset_message_id.empty()) { offset_message_id = "0"; } @@ -2026,9 +1991,7 @@ class CliClient final : public Actor { string offset_message_id; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(offset_message_id, args) = split(args); + get_args(args, chat_id, offset_message_id, args); if (offset_message_id.empty()) { offset_message_id = "0"; } @@ -2041,9 +2004,7 @@ class CliClient final : public Actor { string offset_message_id; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(offset_message_id, args) = split(args); + get_args(args, chat_id, offset_message_id, args); if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } @@ -2056,9 +2017,7 @@ class CliClient final : public Actor { string offset_message_id; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(offset_message_id, args) = split(args); + get_args(args, chat_id, offset_message_id, args); if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } @@ -2069,20 +2028,16 @@ class CliClient final : public Actor { } else if (op == "gcmc") { string chat_id; string filter; - string return_local; - - std::tie(chat_id, args) = split(args); - std::tie(filter, return_local) = split(args); - - send_request(td_api::make_object( - as_chat_id(chat_id), as_search_messages_filter(filter), as_bool(return_local))); + bool return_local; + get_args(args, chat_id, filter, return_local); + send_request(td_api::make_object(as_chat_id(chat_id), + as_search_messages_filter(filter), return_local)); } else if (op == "gup" || op == "gupp") { string user_id; string offset; int32 limit; - std::tie(user_id, args) = split(args); - std::tie(offset, args) = split(args); + get_args(args, user_id, offset, args); if (offset.empty()) { offset = "0"; } @@ -2097,7 +2052,7 @@ class CliClient final : public Actor { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "glti") { send_request(td_api::make_object(as_bool(args))); @@ -2106,18 +2061,14 @@ class CliClient final : public Actor { } else if (op == "glps") { string language_code; string keys; - - std::tie(language_code, keys) = split(args); + get_args(args, language_code, keys); send_request(td_api::make_object(language_code, full_split(keys))); } else if (op == "glpss") { string language_database_path; string language_pack; string language_code; string key; - - std::tie(language_database_path, args) = split(args); - std::tie(language_pack, args) = split(args); - std::tie(language_code, key) = split(args); + get_args(args, language_database_path, language_pack, language_code, key); send_request(td_api::make_object(language_database_path, language_pack, language_code, key)); } else if (op == "synclp") { @@ -2131,11 +2082,7 @@ class CliClient final : public Actor { string name; string native_name; string key; - - std::tie(language_code, args) = split(args); - std::tie(name, args) = split(args); - std::tie(native_name, key) = split(args); - + get_args(args, language_code, name, native_name, key); vector> strings; strings.push_back(td_api::make_object( key, td_api::make_object("Ordinary value"))); @@ -2151,20 +2098,14 @@ class CliClient final : public Actor { string language_code; string name; string native_name; - - std::tie(language_code, args) = split(args); - std::tie(name, native_name) = split(args); - + get_args(args, language_code, name, native_name); send_request(td_api::make_object( as_language_pack_info(language_code, name, native_name))); } else if (op == "sclpsv" || op == "sclpsp" || op == "sclpsd") { string language_code; string key; string value; - - std::tie(language_code, args) = split(args); - std::tie(key, value) = split(args); - + get_args(args, language_code, key, value); td_api::object_ptr str = td_api::make_object(key, nullptr); if (op == "sclsv") { @@ -2184,25 +2125,21 @@ class CliClient final : public Actor { } else if (op == "sob") { string name; string value; - - std::tie(name, value) = split(args); + get_args(args, name, value); send_request(td_api::make_object( name, td_api::make_object(as_bool(value)))); } else if (op == "soe") { send_request(td_api::make_object(args, td_api::make_object())); } else if (op == "soi") { string name; - string value; - - std::tie(name, value) = split(args); - auto value_int = to_integer(value); + int64 value; + get_args(args, name, value); send_request( - td_api::make_object(name, td_api::make_object(value_int))); + td_api::make_object(name, td_api::make_object(value))); } else if (op == "sos") { string name; string value; - - std::tie(name, value) = split(args); + get_args(args, name, value); send_request(td_api::make_object(name, td_api::make_object(value))); } else if (op == "me") { send_request(td_api::make_object()); @@ -2267,10 +2204,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(nullptr, get_solid_background(to_integer(args)), op == "sbgsd")); } else if (op == "sbgg" || op == "sbggd") { - string top_color; - string bottom_color; - std::tie(top_color, bottom_color) = split(args); - auto background_type = get_gradient_background(to_integer(top_color), to_integer(bottom_color)); + int32 top_color; + int32 bottom_color; + get_args(args, top_color, bottom_color); + auto background_type = get_gradient_background(top_color, bottom_color); send_request(td_api::make_object(nullptr, std::move(background_type), op == "sbggd")); } else if (op == "sbgwid" || op == "sbgwidd") { send_request(td_api::make_object( @@ -2299,14 +2236,10 @@ class CliClient final : public Actor { } else if (op == "tme") { send_request(td_api::make_object(args)); } else if (op == "gbms") { - string offset; + int32 offset; string limit; - - std::tie(offset, limit) = split(args); - if (offset.empty()) { - offset = "0"; - } - send_request(td_api::make_object(to_integer(offset), as_limit(limit))); + get_args(args, offset, limit); + send_request(td_api::make_object(offset, as_limit(limit))); } else if (op == "gu") { send_request(td_api::make_object(as_user_id(args))); } else if (op == "gsu") { @@ -2329,17 +2262,13 @@ class CliClient final : public Actor { string is_masks; string offset_sticker_set_id; string limit; - - std::tie(is_masks, args) = split(args); - std::tie(offset_sticker_set_id, limit) = split(args); - + get_args(args, is_masks, offset_sticker_set_id, limit); send_request(td_api::make_object( as_bool(is_masks), to_integer(offset_sticker_set_id), as_limit(limit))); } else if (op == "gtss") { string offset; string limit; - - std::tie(offset, limit) = split(args); + get_args(args, offset, limit); send_request( td_api::make_object(to_integer(offset), as_limit(limit, 1000))); } else if (op == "gatss") { @@ -2354,8 +2283,7 @@ class CliClient final : public Actor { string chat_ids; string exclude_chat_ids; string chat_ids_limit; - std::tie(chat_ids, args) = split(args); - std::tie(exclude_chat_ids, chat_ids_limit) = split(args); + get_args(args, chat_ids, exclude_chat_ids, chat_ids_limit); send_request(td_api::make_object( 10000000, -1, -1, 0, std::vector>(), as_chat_ids(chat_ids), as_chat_ids(exclude_chat_ids), op == "optimize_storage", to_integer(chat_ids_limit))); @@ -2401,9 +2329,7 @@ class CliClient final : public Actor { string received_bytes; string duration; string network_type; - std::tie(sent_bytes, args) = split(args); - std::tie(received_bytes, args) = split(args); - std::tie(duration, network_type) = split(args); + get_args(args, sent_bytes, received_bytes, duration, network_type); send_request( td_api::make_object(td_api::make_object( get_network_type(network_type), to_integer(sent_bytes), to_integer(received_bytes), @@ -2412,8 +2338,7 @@ class CliClient final : public Actor { string sent_bytes; string received_bytes; string network_type; - std::tie(sent_bytes, args) = split(args); - std::tie(received_bytes, network_type) = split(args); + get_args(args, sent_bytes, received_bytes, network_type); send_request( td_api::make_object(td_api::make_object( td_api::make_object(), get_network_type(network_type), @@ -2423,8 +2348,7 @@ class CliClient final : public Actor { } else if (op == "rtc") { string chat_id; string category; - std::tie(chat_id, category) = split(args); - + get_args(args, chat_id, category); send_request(td_api::make_object(get_top_chat_category(category), as_chat_id(chat_id))); } else if (op == "sss") { send_request(td_api::make_object(args)); @@ -2436,10 +2360,7 @@ class CliClient final : public Actor { string set_id; string is_installed; string is_archived; - - std::tie(set_id, args) = split(args); - std::tie(is_installed, is_archived) = split(args); - + get_args(args, set_id, is_installed, is_archived); send_request(td_api::make_object(to_integer(set_id), as_bool(is_installed), as_bool(is_archived))); } else if (op == "vtss") { @@ -2447,9 +2368,7 @@ class CliClient final : public Actor { } else if (op == "riss") { string is_masks; string new_order; - - std::tie(is_masks, new_order) = split(args); - + get_args(args, is_masks, new_order); send_request( td_api::make_object(as_bool(is_masks), to_integers(new_order))); } else if (op == "grs") { @@ -2457,16 +2376,12 @@ class CliClient final : public Actor { } else if (op == "ars") { string is_attached; string sticker_id; - - std::tie(is_attached, sticker_id) = split(args); - + get_args(args, is_attached, sticker_id); send_request(td_api::make_object(as_bool(is_attached), as_input_file_id(sticker_id))); } else if (op == "rrs") { string is_attached; string sticker_id; - - std::tie(is_attached, sticker_id) = split(args); - + get_args(args, is_attached, sticker_id); send_request( td_api::make_object(as_bool(is_attached), as_input_file_id(sticker_id))); } else if (op == "gfs") { @@ -2514,17 +2429,14 @@ class CliClient final : public Actor { string filter; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(filter, args) = split(args); + get_args(args, chat_id, filter, args); std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object(as_chat_id(chat_id), query, limit, get_chat_members_filter(filter))); } else if (op == "gcm") { string chat_id; string user_id; - - std::tie(chat_id, user_id) = split(args); + get_args(args, chat_id, user_id); send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id))); } else if (op == "GetChatAdministrators") { string chat_id = args; @@ -2580,32 +2492,30 @@ class CliClient final : public Actor { } else if (op == "gm") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "gmf") { string chat_id; - string from_message_id_str; - string to_message_id_str; - std::tie(chat_id, args) = split(args); - std::tie(from_message_id_str, to_message_id_str) = split(args); - auto to_message_id = to_integer(to_message_id_str); - for (auto message_id = to_integer(from_message_id_str); message_id <= to_message_id; message_id++) { + int64 from_message_id; + int64 to_message_id; + get_args(args, chat_id, from_message_id, to_message_id); + for (auto message_id = from_message_id; message_id <= to_message_id; message_id++) { send_request(td_api::make_object(as_chat_id(chat_id), message_id << 20)); } } else if (op == "gml") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "grm") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "gmt") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "gcpm") { string chat_id = args; @@ -2613,24 +2523,21 @@ class CliClient final : public Actor { } else if (op == "gms") { string chat_id; string message_ids; - std::tie(chat_id, message_ids) = split(args); + get_args(args, chat_id, message_ids); send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids))); } else if (op == "gmlink") { string chat_id; string message_id; string for_album; string for_comment; - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(for_album, for_comment) = split(args); + get_args(args, chat_id, message_id, for_album, for_comment); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), as_bool(for_album), as_bool(for_comment))); } else if (op == "gmec") { string chat_id; string message_id; string for_album; - std::tie(chat_id, args) = split(args); - std::tie(message_id, for_album) = split(args); + get_args(args, chat_id, message_id, for_album); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), as_bool(for_album))); } else if (op == "gmli") { @@ -2638,22 +2545,21 @@ class CliClient final : public Actor { } else if (op == "gcmbd") { string chat_id; string date; - std::tie(chat_id, date) = split(args); + get_args(args, chat_id, date); send_request(td_api::make_object(as_chat_id(chat_id), to_integer(date))); } else if (op == "gf" || op == "GetFile") { send_request(td_api::make_object(as_file_id(args))); } else if (op == "gfdps") { string file_id; string offset; - std::tie(file_id, offset) = split(args); + get_args(args, file_id, offset); send_request( td_api::make_object(as_file_id(file_id), to_integer(offset))); } else if (op == "rfp") { string file_id; string offset; string count; - std::tie(file_id, args) = split(args); - std::tie(offset, count) = split(args); + get_args(args, file_id, offset, count); send_request(td_api::make_object(as_file_id(file_id), to_integer(offset), to_integer(count))); @@ -2667,13 +2573,7 @@ class CliClient final : public Actor { string height; string scale; string chat_id; - std::tie(latitude, args) = split(args); - std::tie(longitude, args) = split(args); - std::tie(zoom, args) = split(args); - std::tie(width, args) = split(args); - std::tie(height, args) = split(args); - std::tie(scale, chat_id) = split(args); - + get_args(args, latitude, longitude, zoom, width, height, scale, chat_id); send_request(td_api::make_object( as_location(latitude, longitude), to_integer(zoom), to_integer(width), to_integer(height), to_integer(scale), as_chat_id(chat_id))); @@ -2682,13 +2582,10 @@ class CliClient final : public Actor { string priority; string offset; string limit; - std::tie(file_id, args) = split(args); - std::tie(offset, args) = split(args); - std::tie(limit, priority) = split(args); + get_args(args, file_id, offset, limit, priority); if (priority.empty()) { priority = "1"; } - int32 max_file_id = as_file_id(file_id); int32 min_file_id = (op == "dff" ? 1 : max_file_id); for (int32 i = min_file_id; i <= max_file_id; i++) { @@ -2700,7 +2597,7 @@ class CliClient final : public Actor { } else if (op == "uf" || op == "ufs" || op == "ufse") { string file_path; string priority; - std::tie(file_path, priority) = split(args); + get_args(args, file_path, priority); if (priority.empty()) { priority = "1"; } @@ -2718,7 +2615,7 @@ class CliClient final : public Actor { } else if (op == "ufg") { string file_path; string conversion; - std::tie(file_path, conversion) = split(args); + get_args(args, file_path, conversion); send_request(td_api::make_object(as_generated_file(file_path, conversion), td_api::make_object(), 1)); } else if (op == "cuf") { @@ -2729,17 +2626,14 @@ class CliClient final : public Actor { } else if (op == "dm" || op == "dmr") { string chat_id; string message_ids; - std::tie(chat_id, message_ids) = split(args); - + get_args(args, chat_id, message_ids); send_request( td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids), op == "dmr")); } else if (op == "fm" || op == "cm") { string chat_id; string from_chat_id; string message_ids; - std::tie(chat_id, args) = split(args); - std::tie(from_chat_id, message_ids) = split(args); - + get_args(args, chat_id, from_chat_id, message_ids); 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), default_message_send_options(), op[0] == 'c', @@ -2747,8 +2641,7 @@ class CliClient final : public Actor { } else if (op == "resend") { string chat_id; string message_ids; - std::tie(chat_id, message_ids) = split(args); - + get_args(args, chat_id, message_ids); send_request(td_api::make_object(as_chat_id(chat_id), as_message_ids(message_ids))); } else if (op == "csc" || op == "CreateSecretChat") { send_request(td_api::make_object(as_secret_chat_id(args))); @@ -2759,8 +2652,7 @@ class CliClient final : public Actor { } else if (op == "sscttl" || op == "setSecretChatTtl") { string chat_id; string ttl; - std::tie(chat_id, ttl) = split(args); - + get_args(args, chat_id, ttl); send_request(td_api::make_object(as_chat_id(chat_id), to_integer(ttl))); } else if (op == "closeSC" || op == "cancelSC") { send_request(td_api::make_object(as_secret_chat_id(args))); @@ -2777,14 +2669,13 @@ class CliClient final : public Actor { } else if (op == "dc" || op == "DiscardCall") { string call_id; string is_disconnected; - std::tie(call_id, is_disconnected) = split(args); - + get_args(args, call_id, is_disconnected); send_request(td_api::make_object(as_call_id(call_id), as_bool(is_disconnected), 0, Random::fast_bool(), 0)); } else if (op == "scr" || op == "SendCallRating") { string call_id; string rating; - std::tie(call_id, rating) = split(args); + get_args(args, call_id, rating); vector> problems; problems.emplace_back(td_api::make_object()); @@ -2820,22 +2711,20 @@ class CliClient final : public Actor { string group_call_id; string source; string is_speaking; - std::tie(group_call_id, args) = split(args); - std::tie(source, is_speaking) = split(args); + get_args(args, group_call_id, source, is_speaking); send_request(td_api::make_object( as_group_call_id(group_call_id), to_integer(source), as_bool(is_speaking))); } else if (op == "igcp") { string group_call_id; string user_ids; - std::tie(group_call_id, user_ids) = split(args); + get_args(args, group_call_id, user_ids); send_request(td_api::make_object(as_group_call_id(group_call_id), as_user_ids(user_ids))); } else if (op == "tgcpim") { string group_call_id; string user_id; string is_muted; - std::tie(group_call_id, args) = split(args); - std::tie(user_id, is_muted) = split(args); + get_args(args, group_call_id, user_id, is_muted); send_request(td_api::make_object( as_group_call_id(group_call_id), as_user_id(user_id), as_bool(is_muted))); } else if (op == "cgcij") { @@ -2843,7 +2732,7 @@ class CliClient final : public Actor { } else if (op == "lgcp") { string group_call_id; string limit; - std::tie(group_call_id, limit) = split(args); + get_args(args, group_call_id, limit); send_request( td_api::make_object(as_group_call_id(group_call_id), as_limit(limit))); } else if (op == "lgc") { @@ -2922,9 +2811,7 @@ class CliClient final : public Actor { string type; string chat_id; string json; - std::tie(type, args) = split(args); - std::tie(chat_id, json) = split(args); - + get_args(args, type, chat_id, json); auto result = execute(td_api::make_object(json)); if (result->get_id() == td_api::error::ID) { LOG(ERROR) << to_string(result); @@ -2964,19 +2851,19 @@ class CliClient final : public Actor { } else if (op == "tcip" || op == "tcipa" || begins_with(op, "tcip-")) { string chat_id; string is_pinned; - std::tie(chat_id, is_pinned) = split(args); + get_args(args, chat_id, is_pinned); send_request( td_api::make_object(as_chat_list(op), as_chat_id(chat_id), as_bool(is_pinned))); } else if (op == "tcimau") { string chat_id; string is_marked_as_read; - std::tie(chat_id, is_marked_as_read) = split(args); + get_args(args, chat_id, is_marked_as_read); send_request( td_api::make_object(as_chat_id(chat_id), as_bool(is_marked_as_read))); } else if (op == "tmsib") { string chat_id; string is_blocked; - std::tie(chat_id, is_blocked) = split(args); + get_args(args, chat_id, is_blocked); send_request( td_api::make_object(as_message_sender(chat_id), as_bool(is_blocked))); } else if (op == "bmsfr") { @@ -2984,15 +2871,13 @@ class CliClient final : public Actor { string delete_message; string delete_all_messages; string report_spam; - std::tie(message_id, args) = split(args); - std::tie(delete_message, args) = split(args); - std::tie(delete_all_messages, report_spam) = split(args); + get_args(args, message_id, delete_message, delete_all_messages, report_spam); send_request(td_api::make_object( as_message_id(message_id), as_bool(delete_message), as_bool(delete_all_messages), as_bool(report_spam))); } else if (op == "tcddn") { string chat_id; string default_disable_notification; - std::tie(chat_id, default_disable_notification) = split(args); + get_args(args, chat_id, default_disable_notification); send_request(td_api::make_object( as_chat_id(chat_id), as_bool(default_disable_notification))); } else if (op == "spchats" || op == "spchatsa" || begins_with(op, "spchats-")) { @@ -3006,8 +2891,7 @@ class CliClient final : public Actor { string chat_id; string message_thread_id; string action; - std::tie(chat_id, args) = split(args); - std::tie(message_thread_id, action) = split(args); + get_args(args, chat_id, message_thread_id, action); send_request(td_api::make_object( as_chat_id(chat_id), as_message_thread_id(message_thread_id), get_chat_action(action))); } else if (op == "smt" || op == "smtp" || op == "smtf" || op == "smtpf") { @@ -3030,12 +2914,8 @@ class CliClient final : public Actor { string offset; int32 limit; string query; - - std::tie(chat_id, args) = split(args); - std::tie(filter, args) = split(args); - std::tie(offset, args) = split(args); + get_args(args, chat_id, filter, offset, args); std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, offset, limit, as_search_messages_filter(filter))); } else if (op == "ssd") { @@ -3047,7 +2927,7 @@ class CliClient final : public Actor { string reply_to_message_id; string message; - std::tie(chat_id, message) = split(args); + get_args(args, chat_id, message); if (op == "smr") { std::tie(reply_to_message_id, message) = split(message); } @@ -3063,8 +2943,7 @@ class CliClient final : public Actor { string reply_to_message_id; string message; - std::tie(chat_id, args) = split(args); - std::tie(sender_id, message) = split(args); + get_args(args, chat_id, sender_id, message); if (op == "almr") { std::tie(reply_to_message_id, message) = split(message); } @@ -3077,9 +2956,9 @@ class CliClient final : public Actor { string reply_to_message_id; vector photos; - std::tie(chat_id, args) = split(args); + get_args(args, chat_id, args); if (op == "smapr") { - std::tie(reply_to_message_id, args) = split(args); + get_args(args, reply_to_message_id, args); } photos = full_split(args); @@ -3094,7 +2973,7 @@ class CliClient final : public Actor { string chat_id; vector documents; - std::tie(chat_id, args) = split(args); + get_args(args, chat_id, args); documents = full_split(args); send_request(td_api::make_object( @@ -3108,8 +2987,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string message; - std::tie(chat_id, args) = split(args); - std::tie(message_id, message) = split(args); + get_args(args, chat_id, message_id, message); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_formatted_text(message), true, true))); @@ -3117,8 +2995,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string animation; - std::tie(chat_id, args) = split(args); - std::tie(message_id, animation) = split(args); + get_args(args, chat_id, message_id, animation); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(animation), nullptr, vector(), 0, 0, @@ -3127,16 +3004,14 @@ class CliClient final : public Actor { string chat_id; string message_id; string caption; - std::tie(chat_id, args) = split(args); - std::tie(message_id, caption) = split(args); + get_args(args, chat_id, message_id, caption); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), nullptr, as_caption(caption))); } else if (op == "emd") { string chat_id; string message_id; string document; - std::tie(chat_id, args) = split(args); - std::tie(message_id, document) = split(args); + get_args(args, chat_id, message_id, document); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(document), nullptr, false, as_caption("")))); @@ -3144,8 +3019,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string photo; - std::tie(chat_id, args) = split(args); - std::tie(message_id, photo) = split(args); + get_args(args, chat_id, message_id, photo); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(photo), as_input_thumbnail(photo), Auto(), 0, 0, @@ -3155,9 +3029,7 @@ class CliClient final : public Actor { string message_id; string video; string thumbnail; - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(video, thumbnail) = split(args); + get_args(args, chat_id, message_id, video, thumbnail); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, td_api::make_object(as_input_file(video), as_input_thumbnail(thumbnail), Auto(), 1, @@ -3170,12 +3042,7 @@ class CliClient final : public Actor { string accuracy; string heading; string proximity_alert_radius; - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(latitude, args) = split(args); - std::tie(longitude, args) = split(args); - std::tie(accuracy, args) = split(args); - std::tie(heading, proximity_alert_radius) = split(args); + get_args(args, chat_id, message_id, latitude, longitude, accuracy, heading, proximity_alert_radius); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude, accuracy), to_integer(heading), to_integer(proximity_alert_radius))); @@ -3183,8 +3050,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string date; - std::tie(chat_id, args) = split(args); - std::tie(message_id, date) = split(args); + get_args(args, chat_id, message_id, date); 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") { @@ -3193,35 +3059,31 @@ class CliClient final : public Actor { string bot_id; string chat_id; string parameter; - std::tie(bot_id, args) = split(args); - std::tie(chat_id, parameter) = split(args); + get_args(args, bot_id, chat_id, parameter); send_request( td_api::make_object(as_user_id(bot_id), as_chat_id(chat_id), parameter)); } else if (op == "giqr") { string bot_id; string query; - std::tie(bot_id, query) = split(args); + get_args(args, bot_id, query); send_request(td_api::make_object(as_user_id(bot_id), 0, nullptr, query, "")); } else if (op == "giqro") { string bot_id; string offset; string query; - std::tie(bot_id, args) = split(args); - std::tie(offset, query) = split(args); + get_args(args, bot_id, offset, query); send_request(td_api::make_object(as_user_id(bot_id), 0, nullptr, query, offset)); } else if (op == "giqrl") { string bot_id; string query; - std::tie(bot_id, query) = split(args); + get_args(args, bot_id, query); send_request(td_api::make_object(as_user_id(bot_id), 0, as_location("1.1", "2.2"), query, "")); } else if (op == "siqr" || op == "siqrh") { string chat_id; string query_id; string result_id; - std::tie(chat_id, args) = split(args); - std::tie(query_id, result_id) = split(args); - + get_args(args, chat_id, query_id, result_id); auto chat = as_chat_id(chat_id); send_request(td_api::make_object( chat, as_message_thread_id(message_thread_id_), 0, default_message_send_options(), @@ -3230,8 +3092,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string data; - std::tie(chat_id, args) = split(args); - std::tie(message_id, data) = split(args); + get_args(args, chat_id, message_id, data); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), td_api::make_object(data))); } else if (op == "gcpqa") { @@ -3239,16 +3100,14 @@ class CliClient final : public Actor { string message_id; string password; string data; - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(password, data) = split(args); + get_args(args, chat_id, message_id, password, data); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), td_api::make_object(password, data))); } else if (op == "gcgqa") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(message_id), td_api::make_object(""))); } else if (op == "san") { @@ -3257,11 +3116,7 @@ class CliClient final : public Actor { string width; string height; string caption; - std::tie(chat_id, args) = split(args); - std::tie(animation_path, args) = split(args); - std::tie(width, args) = split(args); - std::tie(height, caption) = split(args); - + get_args(args, chat_id, animation_path, width, height, caption); send_message(chat_id, td_api::make_object( as_input_file(animation_path), nullptr, vector(), 60, to_integer(width), to_integer(height), as_caption(caption))); @@ -3269,30 +3124,26 @@ class CliClient final : public Actor { string chat_id; string animation_path; string animation_conversion; - std::tie(chat_id, args) = split(args); - std::tie(animation_path, animation_conversion) = split(args); + get_args(args, chat_id, animation_path, animation_conversion); send_message(chat_id, td_api::make_object( as_generated_file(animation_path, animation_conversion), nullptr, vector(), 60, 0, 0, as_caption(""))); } else if (op == "sanid") { string chat_id; string file_id; - std::tie(chat_id, file_id) = split(args); - + get_args(args, chat_id, file_id); send_message(chat_id, td_api::make_object( as_input_file_id(file_id), nullptr, vector(), 0, 0, 0, as_caption(""))); } else if (op == "sanurl") { string chat_id; string url; - std::tie(chat_id, url) = split(args); - + get_args(args, chat_id, url); send_message(chat_id, td_api::make_object( as_generated_file(url, "#url#"), nullptr, vector(), 0, 0, 0, as_caption(""))); } else if (op == "sanurl2") { string chat_id; string url; - std::tie(chat_id, url) = split(args); - + get_args(args, chat_id, url); send_message(chat_id, td_api::make_object( as_remote_file(url), nullptr, vector(), 0, 0, 0, as_caption(""))); } else if (op == "sau") { @@ -3301,18 +3152,14 @@ class CliClient final : public Actor { string duration; string title; string performer; - std::tie(chat_id, args) = split(args); - std::tie(audio_path, args) = split(args); - std::tie(duration, args) = split(args); - std::tie(title, performer) = split(args); - + get_args(args, chat_id, audio_path, duration, title, performer); send_message(chat_id, td_api::make_object(as_input_file(audio_path), nullptr, to_integer(duration), title, performer, as_caption("audio caption"))); } else if (op == "svoice") { string chat_id; string voice_path; - std::tie(chat_id, voice_path) = split(args); + get_args(args, chat_id, voice_path); send_message(chat_id, td_api::make_object(as_input_file(voice_path), 0, "abacaba", as_caption("voice caption"))); @@ -3322,38 +3169,30 @@ class CliClient final : public Actor { string first_name; string last_name; string user_id; - std::tie(chat_id, args) = split(args); - std::tie(phone_number, args) = split(args); - std::tie(first_name, args) = split(args); - std::tie(last_name, user_id) = split(args); - + get_args(args, chat_id, phone_number, first_name, last_name, user_id); send_message(chat_id, td_api::make_object(td_api::make_object( phone_number, first_name, last_name, string(), as_user_id(user_id)))); } else if (op == "sf" || op == "scopy") { string chat_id; string from_chat_id; string from_message_id; - std::tie(chat_id, args) = split(args); - std::tie(from_chat_id, from_message_id) = split(args); - + get_args(args, chat_id, from_chat_id, from_message_id); td_api::object_ptr copy_options; if (op == "scopy") { copy_options = td_api::make_object(true, Random::fast_bool(), as_caption("_as_d")); } - 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; - std::tie(chat_id, emoji) = split(args); - + get_args(args, chat_id, emoji); send_message(chat_id, td_api::make_object(emoji, op == "sdicecd")); } else if (op == "sd" || op == "sdf") { string chat_id; string document_path; - std::tie(chat_id, document_path) = split(args); + get_args(args, chat_id, document_path); send_message(chat_id, td_api::make_object( as_input_file(document_path), nullptr, op == "sdf", as_caption(u8"\u1680\u180Etest \u180E\n\u180E\n\u180E\n cap\ttion\u180E\u180E"))); @@ -3361,8 +3200,7 @@ class CliClient final : public Actor { string chat_id; string document_path; string thumbnail_path; - std::tie(chat_id, args) = split(args); - std::tie(document_path, thumbnail_path) = split(args); + get_args(args, chat_id, document_path, thumbnail_path); send_message(chat_id, td_api::make_object( as_input_file(document_path), as_input_thumbnail(thumbnail_path), op == "sdtf", as_caption("test caption"))); @@ -3370,8 +3208,7 @@ class CliClient final : public Actor { string chat_id; string document_path; string document_conversion; - std::tie(chat_id, args) = split(args); - std::tie(document_path, document_conversion) = split(args); + get_args(args, chat_id, document_path, document_conversion); if (op == "sdgu") { send_request( td_api::make_object(as_generated_file(document_path, document_conversion), nullptr, 1)); @@ -3384,9 +3221,7 @@ class CliClient final : public Actor { string document_path; string thumbnail_path; string thumbnail_conversion; - std::tie(chat_id, args) = split(args); - std::tie(document_path, args) = split(args); - std::tie(thumbnail_path, thumbnail_conversion) = split(args); + get_args(args, chat_id, document_path, thumbnail_path, thumbnail_conversion); send_message(chat_id, td_api::make_object( as_input_file(document_path), as_input_thumbnail(thumbnail_path, thumbnail_conversion), false, as_caption("test caption"))); @@ -3396,10 +3231,7 @@ class CliClient final : public Actor { string document_conversion; string thumbnail_path; string thumbnail_conversion; - std::tie(chat_id, args) = split(args); - std::tie(document_path, args) = split(args); - std::tie(document_conversion, args) = split(args); - std::tie(thumbnail_path, thumbnail_conversion) = split(args); + get_args(args, chat_id, document_path, document_conversion, thumbnail_path, thumbnail_conversion); send_message(chat_id, td_api::make_object( as_generated_file(document_path, document_conversion), @@ -3407,32 +3239,27 @@ class CliClient final : public Actor { } else if (op == "sdid") { string chat_id; string file_id; - std::tie(chat_id, file_id) = split(args); + get_args(args, chat_id, file_id); send_message(chat_id, td_api::make_object(as_input_file_id(file_id), nullptr, false, as_caption(""))); } else if (op == "sdurl") { string chat_id; string url; - std::tie(chat_id, url) = split(args); - + get_args(args, chat_id, url); send_message(chat_id, td_api::make_object(as_remote_file(url), nullptr, false, as_caption(""))); } else if (op == "sg") { string chat_id; string bot_user_id; string game_short_name; - std::tie(chat_id, args) = split(args); - std::tie(bot_user_id, game_short_name) = split(args); + get_args(args, chat_id, bot_user_id, game_short_name); send_message(chat_id, td_api::make_object(as_user_id(bot_user_id), game_short_name)); } else if (op == "sl") { string chat_id; string latitude; string longitude; string accuracy; - std::tie(chat_id, args) = split(args); - std::tie(latitude, args) = split(args); - std::tie(longitude, accuracy) = split(args); - + get_args(args, chat_id, latitude, longitude, accuracy); send_message(chat_id, td_api::make_object( as_location(latitude, longitude, accuracy), 0, 0, 0)); } else if (op == "sll") { @@ -3443,21 +3270,14 @@ class CliClient final : public Actor { string accuracy; string heading; string proximity_alert_radius; - std::tie(chat_id, args) = split(args); - std::tie(period, args) = split(args); - std::tie(latitude, args) = split(args); - std::tie(longitude, args) = split(args); - std::tie(accuracy, args) = split(args); - std::tie(heading, proximity_alert_radius) = split(args); - + get_args(args, chat_id, period, latitude, longitude, accuracy, heading, proximity_alert_radius); send_message(chat_id, td_api::make_object( as_location(latitude, longitude, accuracy), to_integer(period), to_integer(heading), to_integer(proximity_alert_radius))); } else if (op == "spoll" || op == "spollm" || op == "spollp" || op == "squiz") { string chat_id; string question; - std::tie(chat_id, args) = split(args); - std::tie(question, args) = split(args); + get_args(args, chat_id, question, args); auto options = full_split(args); td_api::object_ptr poll_type; @@ -3474,8 +3294,7 @@ class CliClient final : public Actor { string photo_path; string sticker_file_ids_str; vector sticker_file_ids; - std::tie(chat_id, args) = split(args); - std::tie(sticker_file_ids_str, photo_path) = split(args); + get_args(args, chat_id, sticker_file_ids_str, photo_path); if (trim(photo_path).empty()) { photo_path = sticker_file_ids_str; } else { @@ -3490,10 +3309,7 @@ class CliClient final : public Actor { string photo_path; string conversion; string expected_size; - std::tie(chat_id, args) = split(args); - std::tie(photo_path, args) = split(args); - std::tie(conversion, expected_size) = split(args); - + get_args(args, chat_id, photo_path, conversion, expected_size); send_message(chat_id, td_api::make_object( as_generated_file(photo_path, conversion, to_integer(expected_size)), nullptr, vector(), 0, 0, as_caption(""), op == "spgttl" ? 10 : 0)); @@ -3501,8 +3317,7 @@ class CliClient final : public Actor { string chat_id; string photo_path; string thumbnail_path; - std::tie(chat_id, args) = split(args); - std::tie(photo_path, thumbnail_path) = split(args); + get_args(args, chat_id, photo_path, thumbnail_path); send_message(chat_id, td_api::make_object(as_input_file(photo_path), as_input_thumbnail(thumbnail_path, 90, 89), @@ -3512,10 +3327,7 @@ class CliClient final : public Actor { string photo_path; string thumbnail_path; string thumbnail_conversion; - std::tie(chat_id, args) = split(args); - std::tie(photo_path, args) = split(args); - std::tie(thumbnail_path, thumbnail_conversion) = split(args); - + get_args(args, chat_id, photo_path, thumbnail_path, thumbnail_conversion); send_message(chat_id, td_api::make_object( as_input_file(photo_path), as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89), @@ -3526,12 +3338,7 @@ class CliClient final : public Actor { string conversion; string thumbnail_path; string thumbnail_conversion; - - std::tie(chat_id, args) = split(args); - std::tie(photo_path, args) = split(args); - std::tie(conversion, args) = split(args); - std::tie(thumbnail_path, thumbnail_conversion) = split(args); - + get_args(args, chat_id, photo_path, conversion, thumbnail_path, thumbnail_conversion); send_message(chat_id, td_api::make_object( as_generated_file(photo_path, conversion), as_input_thumbnail(thumbnail_path, thumbnail_conversion, 90, 89), vector(), 0, 0, @@ -3539,32 +3346,27 @@ class CliClient final : public Actor { } else if (op == "spid") { string chat_id; string file_id; - std::tie(chat_id, file_id) = split(args); + get_args(args, chat_id, file_id); send_message(chat_id, td_api::make_object(as_input_file_id(file_id), nullptr, vector(), 0, 0, as_caption(""), 0)); } else if (op == "ss") { string chat_id; string sticker_path; - std::tie(chat_id, sticker_path) = split(args); - + get_args(args, chat_id, sticker_path); send_message(chat_id, td_api::make_object(as_input_file(sticker_path), nullptr, 0, 0, string())); } else if (op == "sstt") { string chat_id; string sticker_path; string thumbnail_path; - std::tie(chat_id, args) = split(args); - std::tie(sticker_path, thumbnail_path) = split(args); - + get_args(args, chat_id, sticker_path, thumbnail_path); send_message(chat_id, td_api::make_object( as_input_file(sticker_path), as_input_thumbnail(thumbnail_path), 0, 0, string())); } else if (op == "ssid") { string chat_id; string file_id; string emoji; - std::tie(chat_id, args) = split(args); - std::tie(file_id, emoji) = split(args); - + get_args(args, chat_id, file_id, emoji); send_message(chat_id, td_api::make_object(as_input_file_id(file_id), nullptr, 0, 0, emoji)); } else if (op == "sv" || op == "svttl") { @@ -3572,8 +3374,7 @@ class CliClient final : public Actor { string video_path; string sticker_file_ids_str; vector sticker_file_ids; - std::tie(chat_id, args) = split(args); - std::tie(sticker_file_ids_str, video_path) = split(args); + get_args(args, chat_id, sticker_file_ids_str, video_path); if (trim(video_path).empty()) { video_path = sticker_file_ids_str; } else { @@ -3587,8 +3388,7 @@ class CliClient final : public Actor { string chat_id; string video; string thumbnail; - std::tie(chat_id, args) = split(args); - std::tie(video, thumbnail) = split(args); + get_args(args, chat_id, video, thumbnail); send_message(chat_id, td_api::make_object( as_input_file(video), as_input_thumbnail(thumbnail), vector(), 0, 0, 0, true, @@ -3596,12 +3396,11 @@ class CliClient final : public Actor { } else if (op == "svn") { string chat_id; string video_path; - std::tie(chat_id, video_path) = split(args); + get_args(args, chat_id, video_path); send_message(chat_id, td_api::make_object(as_input_file(video_path), nullptr, 1, 5)); } else if (op == "svenue") { string chat_id; - string latitude; string longitude; string accuracy; @@ -3610,15 +3409,7 @@ class CliClient final : public Actor { string provider; string venue_id; string venue_type; - std::tie(chat_id, args) = split(args); - std::tie(latitude, args) = split(args); - std::tie(longitude, args) = split(args); - std::tie(accuracy, args) = split(args); - std::tie(title, args) = split(args); - std::tie(address, args) = split(args); - std::tie(provider, args) = split(args); - std::tie(venue_id, venue_type) = split(args); - + get_args(args, chat_id, latitude, longitude, accuracy, title, address, provider, venue_id, venue_type); send_message(chat_id, td_api::make_object(td_api::make_object( as_location(latitude, longitude, accuracy), title, address, provider, venue_id, venue_type))); @@ -3630,20 +3421,18 @@ class CliClient final : public Actor { string chat_id; string remove_from_the_chat_list; string revoke; - std::tie(chat_id, args) = split(args); - std::tie(remove_from_the_chat_list, revoke) = split(args); + get_args(args, chat_id, remove_from_the_chat_list, revoke); send_request(td_api::make_object(as_chat_id(chat_id), as_bool(remove_from_the_chat_list), as_bool(revoke))); } else if (op == "dmfu") { string chat_id; string user_id; - std::tie(chat_id, user_id) = split(args); + get_args(args, chat_id, user_id); send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id))); } else if (op == "cnbgc") { string user_ids_string; string title; - std::tie(user_ids_string, title) = split(args); - + get_args(args, user_ids_string, title); send_request(td_api::make_object(as_user_ids(user_ids_string), title)); } else if (op == "cnch") { send_request(td_api::make_object(args, true, "Description", nullptr)); @@ -3674,21 +3463,18 @@ class CliClient final : public Actor { } else if (op == "cpc") { string user_id; string force; - - std::tie(user_id, force) = split(args); + get_args(args, user_id, force); send_request(td_api::make_object(as_user_id(user_id), as_bool(force))); } else if (op == "cbgc") { string basic_group_id; string force; - - std::tie(basic_group_id, force) = split(args); + get_args(args, basic_group_id, force); send_request( td_api::make_object(as_basic_group_id(basic_group_id), as_bool(force))); } else if (op == "csgc" || op == "cchc") { string supergroup_id; string force; - - std::tie(supergroup_id, force) = split(args); + get_args(args, supergroup_id, force); send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_bool(force))); } else if (op == "gcltac") { string chat_id = args; @@ -3708,8 +3494,7 @@ class CliClient final : public Actor { } else if (op == "ecf") { string chat_filter_id; string filter; - - std::tie(chat_filter_id, filter) = split(args); + get_args(args, chat_filter_id, filter); send_request( td_api::make_object(as_chat_filter_id(chat_filter_id), as_chat_filter(filter))); } else if (op == "dcf") { @@ -3723,8 +3508,7 @@ class CliClient final : public Actor { } else if (op == "sct") { string chat_id; string title; - - std::tie(chat_id, title) = split(args); + get_args(args, chat_id, title); send_request(td_api::make_object(as_chat_id(chat_id), title)); } else if (op == "scpe") { string chat_id = args; @@ -3733,32 +3517,27 @@ class CliClient final : public Actor { } else if (op == "scpp") { string chat_id; string photo_id; - - std::tie(chat_id, photo_id) = split(args); + get_args(args, chat_id, photo_id); send_request(td_api::make_object( as_chat_id(chat_id), td_api::make_object(to_integer(photo_id)))); } else if (op == "scp") { string chat_id; string photo_path; - - std::tie(chat_id, photo_path) = split(args); + get_args(args, chat_id, photo_path); send_request(td_api::make_object( as_chat_id(chat_id), td_api::make_object(as_input_file(photo_path)))); } else if (op == "scpa" || op == "scpv") { string chat_id; string animation; string main_frame_timestamp; - - std::tie(chat_id, args) = split(args); - std::tie(animation, main_frame_timestamp) = split(args); + get_args(args, chat_id, animation, main_frame_timestamp); send_request(td_api::make_object( as_chat_id(chat_id), td_api::make_object(as_input_file(animation), to_double(main_frame_timestamp)))); } else if (op == "scperm") { string chat_id; string permissions; - - std::tie(chat_id, permissions) = split(args); + get_args(args, chat_id, permissions); if (permissions.size() == 8) { auto &s = permissions; send_request(td_api::make_object( @@ -3771,31 +3550,25 @@ class CliClient final : public Actor { } else if (op == "sccd") { string chat_id; string client_data; - - std::tie(chat_id, client_data) = split(args); + get_args(args, chat_id, client_data); send_request(td_api::make_object(as_chat_id(chat_id), client_data)); } else if (op == "acm") { string chat_id; string user_id; string forward_limit; - - std::tie(chat_id, args) = split(args); - std::tie(user_id, forward_limit) = split(args); + get_args(args, chat_id, user_id, forward_limit); send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), to_integer(forward_limit))); } else if (op == "acms") { string chat_id; string user_ids; - - std::tie(chat_id, user_ids) = split(args); + get_args(args, chat_id, user_ids); send_request(td_api::make_object(as_chat_id(chat_id), as_user_ids(user_ids))); } else if (op == "spolla") { string chat_id; string message_id; string option_ids; - - std::tie(chat_id, args) = split(args); - std::tie(message_id, option_ids) = split(args); + get_args(args, chat_id, message_id, option_ids); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), to_integers(option_ids))); } else if (op == "gpollv") { @@ -3804,19 +3577,14 @@ class CliClient final : public Actor { string option_id; string offset; string limit; - - std::tie(chat_id, args) = split(args); - std::tie(message_id, args) = split(args); - std::tie(option_id, args) = split(args); - std::tie(offset, limit) = split(args); + get_args(args, chat_id, message_id, option_id, offset, limit); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), to_integer(option_id), to_integer(offset), as_limit(limit))); } else if (op == "stoppoll") { string chat_id; string message_id; - - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), nullptr)); } else { op_not_found_count++; @@ -3827,9 +3595,7 @@ class CliClient final : public Actor { string user_id; string status_str; td_api::object_ptr status; - - std::tie(chat_id, args) = split(args); - std::tie(user_id, status_str) = split(args); + get_args(args, chat_id, user_id, status_str); if (status_str == "member") { status = td_api::make_object(); } else if (status_str == "left") { @@ -3896,16 +3662,13 @@ class CliClient final : public Actor { string chat_id; string user_id; string password; - - std::tie(chat_id, args) = split(args); - std::tie(user_id, password) = split(args); + get_args(args, chat_id, user_id, password); send_request( td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), password)); } else if (op == "log") { string chat_id; string limit; - - std::tie(chat_id, limit) = split(args); + get_args(args, chat_id, limit); send_request(td_api::make_object(as_chat_id(chat_id), "", 0, as_limit(limit), nullptr, vector())); } else if (op == "join") { @@ -3915,8 +3678,7 @@ class CliClient final : public Actor { } else if (op == "dcm") { string chat_id; string user_id_str; - - std::tie(chat_id, user_id_str) = split(args); + get_args(args, chat_id, user_id_str); auto user_id = as_user_id(user_id_str); td_api::object_ptr status = td_api::make_object(); if (user_id == my_id_) { @@ -3926,7 +3688,7 @@ class CliClient final : public Actor { } else if (op == "sn") { string first_name; string last_name; - std::tie(first_name, last_name) = split(args); + get_args(args, first_name, last_name); send_request(td_api::make_object(first_name, last_name)); } else if (op == "sb") { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); @@ -3935,76 +3697,64 @@ class CliClient final : public Actor { } else if (op == "ccun") { string chat_id; string username; - - std::tie(chat_id, username) = split(args); + get_args(args, chat_id, username); send_request(td_api::make_object(as_chat_id(chat_id), username)); } else if (op == "ssgun" || op == "schun") { string supergroup_id; string username; - - std::tie(supergroup_id, username) = split(args); + get_args(args, supergroup_id, username); send_request(td_api::make_object(as_supergroup_id(supergroup_id), username)); } else if (op == "ssgss") { string supergroup_id; string sticker_set_id; - - std::tie(supergroup_id, sticker_set_id) = split(args); + get_args(args, supergroup_id, sticker_set_id); send_request(td_api::make_object(as_supergroup_id(supergroup_id), to_integer(sticker_set_id))); } else if (op == "tsgp") { string supergroup_id; string is_all_history_available; - - std::tie(supergroup_id, is_all_history_available) = split(args); + get_args(args, supergroup_id, is_all_history_available); send_request(td_api::make_object( as_supergroup_id(supergroup_id), as_bool(is_all_history_available))); } else if (op == "tsgsm") { string supergroup_id; string sign_messages; - - std::tie(supergroup_id, sign_messages) = split(args); + get_args(args, supergroup_id, sign_messages); send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_bool(sign_messages))); } else if (op == "scd") { string chat_id; string description; - - std::tie(chat_id, description) = split(args); + get_args(args, chat_id, description); send_request(td_api::make_object(as_chat_id(chat_id), description)); } else if (op == "scdg") { string chat_id; string group_chat_id; - - std::tie(chat_id, group_chat_id) = split(args); + get_args(args, chat_id, group_chat_id); send_request(td_api::make_object(as_chat_id(chat_id), as_chat_id(group_chat_id))); } else if (op == "scl") { string chat_id; string latitude; string longitude; - - std::tie(chat_id, args) = split(args); - std::tie(latitude, longitude) = split(args); + get_args(args, chat_id, latitude, longitude); send_request(td_api::make_object( as_chat_id(chat_id), td_api::make_object(as_location(latitude, longitude), "address"))); } else if (op == "scsmd") { string chat_id; string slow_mode_delay; - - std::tie(chat_id, slow_mode_delay) = split(args); + get_args(args, chat_id, slow_mode_delay); send_request( td_api::make_object(as_chat_id(chat_id), to_integer(slow_mode_delay))); } else if (op == "pcm" || op == "pcms" || op == "pcmo") { string chat_id; string message_id; - - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), op == "pcms", op == "pcmo")); } else if (op == "upcm") { string chat_id; string message_id; - - std::tie(chat_id, message_id) = split(args); + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "uacm") { string chat_id = args; @@ -4028,14 +3778,12 @@ class CliClient final : public Actor { } else if (op == "scn") { string latitude; string longitude; - - std::tie(latitude, longitude) = split(args); + get_args(args, latitude, longitude); send_request(td_api::make_object(as_location(latitude, longitude))); } else if (op == "sloc") { string latitude; string longitude; - - std::tie(latitude, longitude) = split(args); + get_args(args, latitude, longitude); send_request(td_api::make_object(as_location(latitude, longitude))); } else if (op == "sco") { int32 limit; @@ -4053,8 +3801,7 @@ class CliClient final : public Actor { } else if (op == "gwpiv") { string url; string force_full; - std::tie(url, force_full) = split(args); - + get_args(args, url, force_full); send_request(td_api::make_object(url, as_bool(force_full))); } else if (op == "sppp") { send_request(td_api::make_object( @@ -4065,8 +3812,7 @@ class CliClient final : public Actor { } else if (op == "sppa" || op == "sppv") { string animation; string main_frame_timestamp; - std::tie(animation, main_frame_timestamp) = split(args); - + get_args(args, animation, main_frame_timestamp); send_request(td_api::make_object(td_api::make_object( as_input_file(animation), to_double(main_frame_timestamp)))); } else if (op == "sh") { @@ -4079,9 +3825,9 @@ class CliClient final : public Actor { string chat_id; string message_thread_id; string message_ids; - std::tie(chat_id, message_ids) = split(args); + get_args(args, chat_id, message_ids); if (op == "viewt") { - std::tie(message_thread_id, message_ids) = split(message_ids); + get_args(message_ids, message_thread_id, message_ids); } send_request(td_api::make_object( @@ -4089,8 +3835,7 @@ class CliClient final : public Actor { } else if (op == "omc") { string chat_id; string message_id; - std::tie(chat_id, message_id) = split(args); - + get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "racm") { string chat_id = args; @@ -4109,7 +3854,7 @@ class CliClient final : public Actor { string chat_id_or_scope; string settings; - std::tie(chat_id_or_scope, settings) = split(args); + get_args(args, chat_id_or_scope, settings); string mute_for; string sound; @@ -4142,14 +3887,14 @@ class CliClient final : public Actor { } else if (op == "rn") { string group_id; string notification_ids; - std::tie(group_id, notification_ids) = split(args); + get_args(args, group_id, notification_ids); for (auto notification_id : to_integers(notification_ids)) { send_request(td_api::make_object(to_integer(group_id), notification_id)); } } else if (op == "rng") { string group_id; string max_notification_id; - std::tie(group_id, max_notification_id) = split(args); + get_args(args, group_id, max_notification_id); send_request(td_api::make_object(to_integer(group_id), to_integer(max_notification_id))); } else if (op == "rcab") { @@ -4159,8 +3904,7 @@ class CliClient final : public Actor { string chat_id; string reason_str; string message_ids; - std::tie(chat_id, args) = split(args); - std::tie(reason_str, message_ids) = split(args); + get_args(args, chat_id, reason_str, message_ids); td_api::object_ptr reason; if (reason_str == "spam") { @@ -4185,33 +3929,26 @@ class CliClient final : public Actor { string chat_id; string parameters; string is_dark; - std::tie(chat_id, args) = split(args); - std::tie(parameters, is_dark) = split(args); - + get_args(args, chat_id, parameters, is_dark); send_request( td_api::make_object(as_chat_id(chat_id), parameters, as_bool(is_dark))); } else if (op == "gcst") { string chat_id; string is_dark; - std::tie(chat_id, is_dark) = split(args); - + get_args(args, chat_id, is_dark); send_request(td_api::make_object(as_chat_id(chat_id), as_bool(is_dark))); } else if (op == "gmst") { string chat_id; string message_id; string is_dark; - std::tie(chat_id, args) = split(args); - std::tie(message_id, is_dark) = split(args); - + get_args(args, chat_id, message_id, is_dark); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), as_bool(is_dark))); } else if (op == "gstg") { string chat_id; string token; string x; - std::tie(chat_id, args) = split(args); - std::tie(token, x) = split(args); - + get_args(args, chat_id, token, x); send_request(td_api::make_object(as_chat_id(chat_id), token, to_integer(x))); } else if (op == "hsa" || op == "glu" || op == "glua") { send_request(td_api::make_object(as_suggested_action(args))); @@ -4219,9 +3956,7 @@ class CliClient final : public Actor { string chat_id; string message_id; string button_id; - std::tie(chat_id, args) = split(args); - std::tie(message_id, button_id) = split(args); - + get_args(args, chat_id, message_id, button_id); if (op == "glui") { send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), as_button_id(button_id))); @@ -4233,8 +3968,7 @@ class CliClient final : public Actor { string supergroup_id; string user_id; string message_ids; - std::tie(supergroup_id, args) = split(args); - std::tie(user_id, message_ids) = split(args); + get_args(args, supergroup_id, user_id, message_ids); send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_user_id(user_id), as_message_ids(message_ids))); @@ -4254,11 +3988,9 @@ class CliClient final : public Actor { string user; string password; if (op[0] == 'e') { - std::tie(proxy_id, args) = split(args); + get_args(args, proxy_id, args); } - std::tie(server, args) = split(args); - std::tie(port, args) = split(args); - std::tie(user, password) = split(args); + get_args(args, server, port, user, password); bool enable = op != "aproxy" && op != "editproxy"; td_api::object_ptr type; if (!user.empty() && password.empty()) { @@ -4342,7 +4074,7 @@ class CliClient final : public Actor { } else if (op == "sltvl" || op == "sltvle" || op == "tag") { string tag; string level; - std::tie(tag, level) = split(args); + get_args(args, tag, level); auto request = td_api::make_object(tag, to_integer(level)); if (op == "sltvl") { send_request(std::move(request)); @@ -4360,8 +4092,7 @@ class CliClient final : public Actor { } else if (op == "alog" || op == "aloge") { string level; string text; - std::tie(level, text) = split(args); - + get_args(args, level, text); auto request = td_api::make_object(to_integer(level), text); if (op == "alog") { send_request(std::move(request)); From e53ffdb101ee83c8cffd1a0424d5c269564aecdd Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 19:59:45 +0300 Subject: [PATCH 17/31] tg_cli: use get_args to read bool parameters. --- td/telegram/cli.cpp | 161 ++++++++++++++++++++------------------------ 1 file changed, 72 insertions(+), 89 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index c5cfeccb7..99b355941 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1706,11 +1706,10 @@ class CliClient final : public Actor { } else if (op == "voi") { string chat_id; string message_id; - string allow_save; - + bool allow_save; get_args(args, chat_id, message_id, allow_save); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - nullptr, as_bool(allow_save))); + nullptr, allow_save)); } else if (op == "spfs") { string chat_id; string message_id; @@ -1959,7 +1958,7 @@ class CliClient final : public Actor { } else if (op == "SC") { string limit; string offset_message_id; - string only_missed; + bool only_missed; get_args(args, limit, offset_message_id, only_missed); if (offset_message_id.empty()) { @@ -1967,7 +1966,7 @@ class CliClient final : public Actor { } send_request(td_api::make_object(as_message_id(offset_message_id), as_limit(limit), - as_bool(only_missed))); + only_missed)); } else if (op == "SCRLM") { string chat_id; string limit; @@ -2124,10 +2123,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "sob") { string name; - string value; + bool value; get_args(args, name, value); - send_request(td_api::make_object( - name, td_api::make_object(as_bool(value)))); + send_request( + td_api::make_object(name, td_api::make_object(value))); } else if (op == "soe") { send_request(td_api::make_object(args, td_api::make_object())); } else if (op == "soi") { @@ -2259,12 +2258,12 @@ class CliClient final : public Actor { } else if (op == "giss") { send_request(td_api::make_object(as_bool(args))); } else if (op == "gass") { - string is_masks; + bool is_masks; string offset_sticker_set_id; string limit; get_args(args, is_masks, offset_sticker_set_id, limit); send_request(td_api::make_object( - as_bool(is_masks), to_integer(offset_sticker_set_id), as_limit(limit))); + is_masks, to_integer(offset_sticker_set_id), as_limit(limit))); } else if (op == "gtss") { string offset; string limit; @@ -2358,32 +2357,29 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "css") { string set_id; - string is_installed; - string is_archived; + bool is_installed; + bool is_archived; get_args(args, set_id, is_installed, is_archived); - send_request(td_api::make_object(to_integer(set_id), as_bool(is_installed), - as_bool(is_archived))); + send_request(td_api::make_object(to_integer(set_id), is_installed, is_archived)); } else if (op == "vtss") { send_request(td_api::make_object(to_integers(args))); } else if (op == "riss") { - string is_masks; + bool is_masks; string new_order; get_args(args, is_masks, new_order); - send_request( - td_api::make_object(as_bool(is_masks), to_integers(new_order))); + send_request(td_api::make_object(is_masks, to_integers(new_order))); } else if (op == "grs") { send_request(td_api::make_object(as_bool(args))); } else if (op == "ars") { - string is_attached; + bool is_attached; string sticker_id; get_args(args, is_attached, sticker_id); - send_request(td_api::make_object(as_bool(is_attached), as_input_file_id(sticker_id))); + send_request(td_api::make_object(is_attached, as_input_file_id(sticker_id))); } else if (op == "rrs") { - string is_attached; + bool is_attached; string sticker_id; get_args(args, is_attached, sticker_id); - send_request( - td_api::make_object(as_bool(is_attached), as_input_file_id(sticker_id))); + send_request(td_api::make_object(is_attached, as_input_file_id(sticker_id))); } else if (op == "gfs") { send_request(td_api::make_object()); } else if (op == "afs") { @@ -2528,18 +2524,18 @@ class CliClient final : public Actor { } else if (op == "gmlink") { string chat_id; string message_id; - string for_album; - string for_comment; + bool for_album; + bool for_comment; get_args(args, chat_id, message_id, for_album, for_comment); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - as_bool(for_album), as_bool(for_comment))); + for_album, for_comment)); } else if (op == "gmec") { string chat_id; string message_id; - string for_album; + bool for_album; get_args(args, chat_id, message_id, for_album); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - as_bool(for_album))); + for_album)); } else if (op == "gmli") { send_request(td_api::make_object(args)); } else if (op == "gcmbd") { @@ -2668,10 +2664,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_call_id(args), "abacaba")); } else if (op == "dc" || op == "DiscardCall") { string call_id; - string is_disconnected; + bool is_disconnected; get_args(args, call_id, is_disconnected); - send_request(td_api::make_object(as_call_id(call_id), as_bool(is_disconnected), 0, - Random::fast_bool(), 0)); + send_request( + td_api::make_object(as_call_id(call_id), is_disconnected, 0, Random::fast_bool(), 0)); } else if (op == "scr" || op == "SendCallRating") { string call_id; string rating; @@ -2710,10 +2706,10 @@ class CliClient final : public Actor { } else if (op == "sgcpis") { string group_call_id; string source; - string is_speaking; + bool is_speaking; get_args(args, group_call_id, source, is_speaking); send_request(td_api::make_object( - as_group_call_id(group_call_id), to_integer(source), as_bool(is_speaking))); + as_group_call_id(group_call_id), to_integer(source), is_speaking)); } else if (op == "igcp") { string group_call_id; string user_ids; @@ -2723,10 +2719,10 @@ class CliClient final : public Actor { } else if (op == "tgcpim") { string group_call_id; string user_id; - string is_muted; + bool is_muted; get_args(args, group_call_id, user_id, is_muted); - send_request(td_api::make_object( - as_group_call_id(group_call_id), as_user_id(user_id), as_bool(is_muted))); + send_request(td_api::make_object(as_group_call_id(group_call_id), + as_user_id(user_id), is_muted)); } else if (op == "cgcij") { send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "lgcp") { @@ -2850,36 +2846,33 @@ class CliClient final : public Actor { send_request(td_api::make_object()); } else if (op == "tcip" || op == "tcipa" || begins_with(op, "tcip-")) { string chat_id; - string is_pinned; + bool is_pinned; get_args(args, chat_id, is_pinned); - send_request( - td_api::make_object(as_chat_list(op), as_chat_id(chat_id), as_bool(is_pinned))); + send_request(td_api::make_object(as_chat_list(op), as_chat_id(chat_id), is_pinned)); } else if (op == "tcimau") { string chat_id; - string is_marked_as_read; + bool is_marked_as_read; get_args(args, chat_id, is_marked_as_read); - send_request( - td_api::make_object(as_chat_id(chat_id), as_bool(is_marked_as_read))); + send_request(td_api::make_object(as_chat_id(chat_id), is_marked_as_read)); } else if (op == "tmsib") { string chat_id; - string is_blocked; + bool is_blocked; get_args(args, chat_id, is_blocked); - send_request( - td_api::make_object(as_message_sender(chat_id), as_bool(is_blocked))); + send_request(td_api::make_object(as_message_sender(chat_id), is_blocked)); } else if (op == "bmsfr") { string message_id; - string delete_message; - string delete_all_messages; - string report_spam; + bool delete_message; + bool delete_all_messages; + bool report_spam; get_args(args, message_id, delete_message, delete_all_messages, report_spam); - send_request(td_api::make_object( - as_message_id(message_id), as_bool(delete_message), as_bool(delete_all_messages), as_bool(report_spam))); + send_request(td_api::make_object(as_message_id(message_id), delete_message, + delete_all_messages, report_spam)); } else if (op == "tcddn") { string chat_id; - string default_disable_notification; + bool default_disable_notification; get_args(args, chat_id, default_disable_notification); - send_request(td_api::make_object( - as_chat_id(chat_id), as_bool(default_disable_notification))); + send_request(td_api::make_object(as_chat_id(chat_id), + default_disable_notification)); } else if (op == "spchats" || op == "spchatsa" || begins_with(op, "spchats-")) { vector chat_ids_str = full_split(args, ' '); vector chat_ids; @@ -3419,11 +3412,11 @@ class CliClient final : public Actor { send_request(td_api::make_object(to_double(args))); } else if (op == "delete") { string chat_id; - string remove_from_the_chat_list; - string revoke; + bool remove_from_the_chat_list; + bool revoke; get_args(args, chat_id, remove_from_the_chat_list, revoke); - send_request(td_api::make_object(as_chat_id(chat_id), - as_bool(remove_from_the_chat_list), as_bool(revoke))); + send_request( + td_api::make_object(as_chat_id(chat_id), remove_from_the_chat_list, revoke)); } else if (op == "dmfu") { string chat_id; string user_id; @@ -3462,20 +3455,19 @@ class CliClient final : public Actor { send_request(td_api::make_object()); } else if (op == "cpc") { string user_id; - string force; + bool force; get_args(args, user_id, force); - send_request(td_api::make_object(as_user_id(user_id), as_bool(force))); + send_request(td_api::make_object(as_user_id(user_id), force)); } else if (op == "cbgc") { string basic_group_id; - string force; + bool force; get_args(args, basic_group_id, force); - send_request( - td_api::make_object(as_basic_group_id(basic_group_id), as_bool(force))); + send_request(td_api::make_object(as_basic_group_id(basic_group_id), force)); } else if (op == "csgc" || op == "cchc") { string supergroup_id; - string force; + bool force; get_args(args, supergroup_id, force); - send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_bool(force))); + send_request(td_api::make_object(as_supergroup_id(supergroup_id), force)); } else if (op == "gcltac") { string chat_id = args; send_request(td_api::make_object(as_chat_id(chat_id))); @@ -3712,16 +3704,16 @@ class CliClient final : public Actor { to_integer(sticker_set_id))); } else if (op == "tsgp") { string supergroup_id; - string is_all_history_available; + bool is_all_history_available; get_args(args, supergroup_id, is_all_history_available); - send_request(td_api::make_object( - as_supergroup_id(supergroup_id), as_bool(is_all_history_available))); + send_request(td_api::make_object(as_supergroup_id(supergroup_id), + is_all_history_available)); } else if (op == "tsgsm") { string supergroup_id; - string sign_messages; + bool sign_messages; get_args(args, supergroup_id, sign_messages); - send_request(td_api::make_object(as_supergroup_id(supergroup_id), - as_bool(sign_messages))); + send_request( + td_api::make_object(as_supergroup_id(supergroup_id), sign_messages)); } else if (op == "scd") { string chat_id; string description; @@ -3800,9 +3792,9 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_caption(args))); } else if (op == "gwpiv") { string url; - string force_full; + bool force_full; get_args(args, url, force_full); - send_request(td_api::make_object(url, as_bool(force_full))); + send_request(td_api::make_object(url, force_full)); } else if (op == "sppp") { send_request(td_api::make_object( td_api::make_object(to_integer(args)))); @@ -3852,21 +3844,13 @@ class CliClient final : public Actor { send_request(td_api::make_object(get_notification_settings_scope(args))); } else if (op == "scns" || op == "ssns") { string chat_id_or_scope; - string settings; - - get_args(args, chat_id_or_scope, settings); - string mute_for; string sound; string show_preview; string disable_pinned_message_notifications; string disable_mention_notifications; - - std::tie(mute_for, settings) = split(settings, ','); - std::tie(sound, settings) = split(settings, ','); - std::tie(show_preview, settings) = split(settings, ','); - std::tie(disable_pinned_message_notifications, disable_mention_notifications) = split(settings, ','); - + get_args(args, chat_id_or_scope, mute_for, sound, show_preview, disable_pinned_message_notifications, + disable_mention_notifications); if (op == "scns") { send_request(td_api::make_object( as_chat_id(chat_id_or_scope), @@ -3928,22 +3912,21 @@ class CliClient final : public Actor { } else if (op == "gcsu") { string chat_id; string parameters; - string is_dark; + bool is_dark; get_args(args, chat_id, parameters, is_dark); - send_request( - td_api::make_object(as_chat_id(chat_id), parameters, as_bool(is_dark))); + send_request(td_api::make_object(as_chat_id(chat_id), parameters, is_dark)); } else if (op == "gcst") { string chat_id; - string is_dark; + bool is_dark; get_args(args, chat_id, is_dark); - send_request(td_api::make_object(as_chat_id(chat_id), as_bool(is_dark))); + send_request(td_api::make_object(as_chat_id(chat_id), is_dark)); } else if (op == "gmst") { string chat_id; string message_id; - string is_dark; + bool is_dark; get_args(args, chat_id, message_id, is_dark); - send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - as_bool(is_dark))); + send_request( + td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), is_dark)); } else if (op == "gstg") { string chat_id; string token; From 3c5c23aeec4e4adc45bd2650ee0ae858ef2c7057 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 20:24:55 +0300 Subject: [PATCH 18/31] Improve error message. --- tdutils/td/utils/misc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdutils/td/utils/misc.h b/tdutils/td/utils/misc.h index 32971b8cc..323d33626 100644 --- a/tdutils/td/utils/misc.h +++ b/tdutils/td/utils/misc.h @@ -320,7 +320,7 @@ template Result to_integer_safe(Slice str) { auto res = to_integer(str); if ((PSLICE() << res) != str) { - return Status::Error(PSLICE() << "Can't parse \"" << str << "\" as number"); + return Status::Error(PSLICE() << "Can't parse \"" << str << "\" as an integer"); } return res; } From 2097d880062a2972312904a263680278687e3909 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 20:26:19 +0300 Subject: [PATCH 19/31] tg_cli: use get_args to read integer parameters. --- td/telegram/cli.cpp | 287 ++++++++++++++++++-------------------------- 1 file changed, 116 insertions(+), 171 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 99b355941..3865f9ab1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1592,17 +1592,16 @@ class CliClient final : public Actor { send_request( td_api::make_object(as_user_id(bot_id), scope, public_key, payload)); } else if (op == "gpafae") { - string form_id; + int32 form_id; string password; get_args(args, form_id, password); - send_request(td_api::make_object( - to_integer(form_id), password)); + send_request(td_api::make_object(form_id, password)); } else if (op == "spaf") { - string form_id; + int32 form_id; string types; get_args(args, form_id, types); - send_request(td_api::make_object(to_integer(form_id), - as_passport_element_types(types))); + send_request( + td_api::make_object(form_id, as_passport_element_types(types))); } else if (op == "gpcl") { send_request(td_api::make_object(args)); } else if (op == "spnvc" || op == "SendPhoneNumberVerificationCode") { @@ -1855,13 +1854,7 @@ class CliClient final : public Actor { std::tie(thread_message_id, args) = split(args); } std::tie(from_message_id, args) = split(args); - if (from_message_id.empty()) { - from_message_id = "0"; - } std::tie(offset, args) = split(args); - if (offset.empty()) { - offset = "0"; - } std::tie(limit, args) = get_search_query(args); if (!args.empty()) { LOG(ERROR) << "Wrong parameters to function getChatHistory specified"; @@ -1942,29 +1935,16 @@ class CliClient final : public Actor { string filter; string limit; string offset_message_id; - string offset; - + int32 offset; get_args(args, chat_id, filter, limit, offset_message_id, offset); - if (offset_message_id.empty()) { - offset_message_id = "0"; - } - if (offset.empty()) { - offset = "0"; - } - send_request(td_api::make_object( - as_chat_id(chat_id), "", nullptr, as_message_id(offset_message_id), to_integer(offset), - as_limit(limit), as_search_messages_filter(filter), 0)); + as_chat_id(chat_id), "", nullptr, as_message_id(offset_message_id), offset, as_limit(limit), + as_search_messages_filter(filter), 0)); } else if (op == "SC") { string limit; string offset_message_id; bool only_missed; - get_args(args, limit, offset_message_id, only_missed); - if (offset_message_id.empty()) { - offset_message_id = "0"; - } - send_request(td_api::make_object(as_message_id(offset_message_id), as_limit(limit), only_missed)); } else if (op == "SCRLM") { @@ -1978,25 +1958,19 @@ class CliClient final : public Actor { int32 limit; string query; get_args(args, chat_id, offset_message_id, args); - if (offset_message_id.empty()) { - offset_message_id = "0"; - } std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, td_api::make_object(), 0)); } else if (op == "SearchDocument") { string chat_id; - string offset_message_id; + int64 offset_message_id; int32 limit; string query; get_args(args, chat_id, offset_message_id, args); - if (offset_message_id.empty()) { - offset_message_id = "0"; - } std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, to_integer(offset_message_id), 0, limit, + as_chat_id(chat_id), query, nullptr, offset_message_id, 0, limit, td_api::make_object(), 0)); } else if (op == "SearchPhoto") { string chat_id; @@ -2033,19 +2007,15 @@ class CliClient final : public Actor { as_search_messages_filter(filter), return_local)); } else if (op == "gup" || op == "gupp") { string user_id; - string offset; + int32 offset; int32 limit; get_args(args, user_id, offset, args); - if (offset.empty()) { - offset = "0"; - } std::tie(limit, args) = get_search_query(args); if (!args.empty()) { LOG(ERROR) << "Wrong parameters to function getUserProfilePhotos specified"; } else { - send_request( - td_api::make_object(as_user_id(user_id), to_integer(offset), limit)); + send_request(td_api::make_object(as_user_id(user_id), offset, limit)); } } else if (op == "dcrm") { string chat_id; @@ -2259,17 +2229,16 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_bool(args))); } else if (op == "gass") { bool is_masks; - string offset_sticker_set_id; + int64 offset_sticker_set_id; string limit; get_args(args, is_masks, offset_sticker_set_id, limit); - send_request(td_api::make_object( - is_masks, to_integer(offset_sticker_set_id), as_limit(limit))); + send_request( + td_api::make_object(is_masks, offset_sticker_set_id, as_limit(limit))); } else if (op == "gtss") { - string offset; + int32 offset; string limit; get_args(args, offset, limit); - send_request( - td_api::make_object(to_integer(offset), as_limit(limit, 1000))); + send_request(td_api::make_object(offset, as_limit(limit, 1000))); } else if (op == "gatss") { send_request(td_api::make_object(as_file_id(args))); } else if (op == "storage") { @@ -2281,11 +2250,11 @@ class CliClient final : public Actor { } else if (op == "optimize_storage" || op == "optimize_storage_all") { string chat_ids; string exclude_chat_ids; - string chat_ids_limit; + int32 chat_ids_limit; get_args(args, chat_ids, exclude_chat_ids, chat_ids_limit); send_request(td_api::make_object( 10000000, -1, -1, 0, std::vector>(), as_chat_ids(chat_ids), - as_chat_ids(exclude_chat_ids), op == "optimize_storage", to_integer(chat_ids_limit))); + as_chat_ids(exclude_chat_ids), op == "optimize_storage", chat_ids_limit)); } else if (op == "clean_storage_default") { send_request(td_api::make_object()); } else if (op == "clean_photos") { @@ -2324,24 +2293,23 @@ class CliClient final : public Actor { send_request(td_api::make_object( td_api::make_object(), get_network_type(args))); } else if (op == "ansc") { - string sent_bytes; - string received_bytes; + int32 sent_bytes; + int32 received_bytes; string duration; string network_type; get_args(args, sent_bytes, received_bytes, duration, network_type); send_request( td_api::make_object(td_api::make_object( - get_network_type(network_type), to_integer(sent_bytes), to_integer(received_bytes), - to_double(duration)))); + get_network_type(network_type), sent_bytes, received_bytes, to_double(duration)))); } else if (op == "ans") { - string sent_bytes; - string received_bytes; + int32 sent_bytes; + int32 received_bytes; string network_type; get_args(args, sent_bytes, received_bytes, network_type); send_request( td_api::make_object(td_api::make_object( - td_api::make_object(), get_network_type(network_type), - to_integer(sent_bytes), to_integer(received_bytes)))); + td_api::make_object(), get_network_type(network_type), sent_bytes, + received_bytes))); } else if (op == "top_chats") { send_request(td_api::make_object(get_top_chat_category(args), 50)); } else if (op == "rtc") { @@ -2356,11 +2324,11 @@ class CliClient final : public Actor { } else if (op == "ssss") { send_request(td_api::make_object(args)); } else if (op == "css") { - string set_id; + int64 set_id; bool is_installed; bool is_archived; get_args(args, set_id, is_installed, is_archived); - send_request(td_api::make_object(to_integer(set_id), is_installed, is_archived)); + send_request(td_api::make_object(set_id, is_installed, is_archived)); } else if (op == "vtss") { send_request(td_api::make_object(to_integers(args))); } else if (op == "riss") { @@ -2441,23 +2409,17 @@ class CliClient final : public Actor { op == "GetSupergroupContacts" || op == "GetSupergroupMembers" || op == "GetSupergroupRestricted" || op == "SearchSupergroupMembers" || op == "SearchSupergroupMentions") { string supergroup_id; - string query; string message_thread_id; string offset; - string limit; + int32 limit; + string query; std::tie(supergroup_id, args) = split(args); - if (op == "GetSupergroupBanned" || op == "GetSupergroupContacts" || op == "GetSupergroupRestricted" || - op == "SearchSupergroupMembers" || op == "SearchSupergroupMentions") { - std::tie(query, args) = split(args); - } if (op == "SearchSupergroupMentions") { std::tie(message_thread_id, args) = split(args); } - std::tie(offset, limit) = split(args); - if (offset.empty()) { - offset = "0"; - } + std::tie(offset, args) = split(args); + std::tie(limit, query) = get_search_query(args); td_api::object_ptr filter; if (op == "GetSupergroupAdministrators") { filter = td_api::make_object(); @@ -2478,7 +2440,7 @@ class CliClient final : public Actor { td_api::make_object(query, as_message_thread_id(message_thread_id)); } send_request(td_api::make_object(as_supergroup_id(supergroup_id), std::move(filter), - to_integer(offset), as_limit(limit))); + to_integer(offset), limit)); } else if (op == "gdialog" || op == "gd") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "open") { @@ -2540,64 +2502,58 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "gcmbd") { string chat_id; - string date; + int32 date; get_args(args, chat_id, date); - send_request(td_api::make_object(as_chat_id(chat_id), to_integer(date))); + send_request(td_api::make_object(as_chat_id(chat_id), date)); } else if (op == "gf" || op == "GetFile") { send_request(td_api::make_object(as_file_id(args))); } else if (op == "gfdps") { string file_id; - string offset; + int32 offset; get_args(args, file_id, offset); - send_request( - td_api::make_object(as_file_id(file_id), to_integer(offset))); + send_request(td_api::make_object(as_file_id(file_id), offset)); } else if (op == "rfp") { string file_id; - string offset; - string count; + int32 offset; + int32 count; get_args(args, file_id, offset, count); - - send_request(td_api::make_object(as_file_id(file_id), to_integer(offset), - to_integer(count))); + send_request(td_api::make_object(as_file_id(file_id), offset, count)); } else if (op == "grf") { send_request(td_api::make_object(args, nullptr)); } else if (op == "gmtf") { string latitude; string longitude; - string zoom; - string width; - string height; - string scale; + int32 zoom; + int32 width; + int32 height; + int32 scale; string chat_id; get_args(args, latitude, longitude, zoom, width, height, scale, chat_id); - send_request(td_api::make_object( - as_location(latitude, longitude), to_integer(zoom), to_integer(width), - to_integer(height), to_integer(scale), as_chat_id(chat_id))); + send_request(td_api::make_object(as_location(latitude, longitude), zoom, width, + height, scale, as_chat_id(chat_id))); } else if (op == "df" || op == "DownloadFile" || op == "dff" || op == "dfs") { string file_id; - string priority; - string offset; + int32 priority; + int32 offset; string limit; get_args(args, file_id, offset, limit, priority); - if (priority.empty()) { - priority = "1"; + if (priority <= 0) { + priority = 1; } int32 max_file_id = as_file_id(file_id); int32 min_file_id = (op == "dff" ? 1 : max_file_id); for (int32 i = min_file_id; i <= max_file_id; i++) { - send_request(td_api::make_object( - i, to_integer(priority), to_integer(offset), as_limit(limit), op == "dfs")); + send_request(td_api::make_object(i, priority, offset, as_limit(limit), op == "dfs")); } } else if (op == "cdf") { send_request(td_api::make_object(as_file_id(args), false)); } else if (op == "uf" || op == "ufs" || op == "ufse") { string file_path; - string priority; + int32 priority; get_args(args, file_path, priority); - if (priority.empty()) { - priority = "1"; + if (priority <= 0) { + priority = 1; } - td_api::object_ptr type = td_api::make_object(); if (op == "ufs") { type = td_api::make_object(); @@ -2605,9 +2561,7 @@ class CliClient final : public Actor { if (op == "ufse") { type = td_api::make_object(); } - - send_request(td_api::make_object(as_input_file(file_path), std::move(type), - to_integer(priority))); + send_request(td_api::make_object(as_input_file(file_path), std::move(type), priority)); } else if (op == "ufg") { string file_path; string conversion; @@ -2647,9 +2601,9 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "sscttl" || op == "setSecretChatTtl") { string chat_id; - string ttl; + int32 ttl; get_args(args, chat_id, ttl); - send_request(td_api::make_object(as_chat_id(chat_id), to_integer(ttl))); + send_request(td_api::make_object(as_chat_id(chat_id), ttl)); } else if (op == "closeSC" || op == "cancelSC") { send_request(td_api::make_object(as_secret_chat_id(args))); } else if (op == "cc" || op == "CreateCall") { @@ -2670,9 +2624,8 @@ class CliClient final : public Actor { td_api::make_object(as_call_id(call_id), is_disconnected, 0, Random::fast_bool(), 0)); } else if (op == "scr" || op == "SendCallRating") { string call_id; - string rating; + int32 rating; get_args(args, call_id, rating); - vector> problems; problems.emplace_back(td_api::make_object()); problems.emplace_back(td_api::make_object()); @@ -2683,7 +2636,7 @@ class CliClient final : public Actor { problems.emplace_back(td_api::make_object()); problems.emplace_back(td_api::make_object()); send_request(td_api::make_object( - as_call_id(call_id), to_integer(rating), "Wow, such good call! (TDLib test)", std::move(problems))); + as_call_id(call_id), rating, "Wow, such good call! (TDLib test)", std::move(problems))); } else if (op == "scdi" || op == "SendCallDebugInformation") { send_request(td_api::make_object(as_call_id(args), "{}")); } else if (op == "cvc") { @@ -2705,11 +2658,11 @@ class CliClient final : public Actor { td_api::make_object(as_group_call_id(args), op == "tgcmnpe")); } else if (op == "sgcpis") { string group_call_id; - string source; + int32 source; bool is_speaking; get_args(args, group_call_id, source, is_speaking); - send_request(td_api::make_object( - as_group_call_id(group_call_id), to_integer(source), is_speaking)); + send_request(td_api::make_object(as_group_call_id(group_call_id), + source, is_speaking)); } else if (op == "igcp") { string group_call_id; string user_ids; @@ -3033,12 +2986,12 @@ class CliClient final : public Actor { string latitude; string longitude; string accuracy; - string heading; - string proximity_alert_radius; + int32 heading; + int32 proximity_alert_radius; get_args(args, chat_id, message_id, latitude, longitude, accuracy, heading, proximity_alert_radius); send_request(td_api::make_object( - as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude, accuracy), - to_integer(heading), to_integer(proximity_alert_radius))); + as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude, accuracy), heading, + proximity_alert_radius)); } else if (op == "emss") { string chat_id; string message_id; @@ -3074,13 +3027,13 @@ class CliClient final : public Actor { query, "")); } else if (op == "siqr" || op == "siqrh") { string chat_id; - string query_id; + int64 query_id; string result_id; get_args(args, chat_id, query_id, result_id); auto chat = as_chat_id(chat_id); send_request(td_api::make_object( - chat, as_message_thread_id(message_thread_id_), 0, default_message_send_options(), - to_integer(query_id), result_id, op == "siqrh")); + chat, as_message_thread_id(message_thread_id_), 0, default_message_send_options(), query_id, result_id, + op == "siqrh")); } else if (op == "gcqa") { string chat_id; string message_id; @@ -3106,13 +3059,13 @@ class CliClient final : public Actor { } else if (op == "san") { string chat_id; string animation_path; - string width; - string height; + int32 width; + int32 height; string caption; get_args(args, chat_id, animation_path, width, height, caption); - send_message(chat_id, td_api::make_object( - as_input_file(animation_path), nullptr, vector(), 60, to_integer(width), - to_integer(height), as_caption(caption))); + send_message(chat_id, td_api::make_object(as_input_file(animation_path), nullptr, + vector(), 60, width, height, + as_caption(caption))); } else if (op == "sang") { string chat_id; string animation_path; @@ -3142,13 +3095,13 @@ class CliClient final : public Actor { } else if (op == "sau") { string chat_id; string audio_path; - string duration; + int32 duration; string title; string performer; get_args(args, chat_id, audio_path, duration, title, performer); - send_message(chat_id, td_api::make_object(as_input_file(audio_path), nullptr, - to_integer(duration), title, - performer, as_caption("audio caption"))); + send_message(chat_id, + td_api::make_object(as_input_file(audio_path), nullptr, duration, title, + performer, as_caption("audio caption"))); } else if (op == "svoice") { string chat_id; string voice_path; @@ -3257,16 +3210,15 @@ class CliClient final : public Actor { as_location(latitude, longitude, accuracy), 0, 0, 0)); } else if (op == "sll") { string chat_id; - string period; + int32 period; string latitude; string longitude; string accuracy; - string heading; - string proximity_alert_radius; + int32 heading; + int32 proximity_alert_radius; get_args(args, chat_id, period, latitude, longitude, accuracy, heading, proximity_alert_radius); send_message(chat_id, td_api::make_object( - as_location(latitude, longitude, accuracy), to_integer(period), - to_integer(heading), to_integer(proximity_alert_radius))); + as_location(latitude, longitude, accuracy), period, heading, proximity_alert_radius)); } else if (op == "spoll" || op == "spollm" || op == "spollp" || op == "squiz") { string chat_id; string question; @@ -3301,11 +3253,11 @@ class CliClient final : public Actor { string chat_id; string photo_path; string conversion; - string expected_size; + int32 expected_size; get_args(args, chat_id, photo_path, conversion, expected_size); send_message(chat_id, td_api::make_object( - as_generated_file(photo_path, conversion, to_integer(expected_size)), nullptr, - vector(), 0, 0, as_caption(""), op == "spgttl" ? 10 : 0)); + as_generated_file(photo_path, conversion, expected_size), nullptr, vector(), 0, + 0, as_caption(""), op == "spgttl" ? 10 : 0)); } else if (op == "spt") { string chat_id; string photo_path; @@ -3508,10 +3460,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id), nullptr)); } else if (op == "scpp") { string chat_id; - string photo_id; + int64 photo_id; get_args(args, chat_id, photo_id); send_request(td_api::make_object( - as_chat_id(chat_id), td_api::make_object(to_integer(photo_id)))); + as_chat_id(chat_id), td_api::make_object(photo_id))); } else if (op == "scp") { string chat_id; string photo_path; @@ -3547,10 +3499,9 @@ class CliClient final : public Actor { } else if (op == "acm") { string chat_id; string user_id; - string forward_limit; + int32 forward_limit; get_args(args, chat_id, user_id, forward_limit); - send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), - to_integer(forward_limit))); + send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), forward_limit)); } else if (op == "acms") { string chat_id; string user_ids; @@ -3566,13 +3517,12 @@ class CliClient final : public Actor { } else if (op == "gpollv") { string chat_id; string message_id; - string option_id; - string offset; + int32 option_id; + int32 offset; string limit; get_args(args, chat_id, message_id, option_id, offset, limit); - send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - to_integer(option_id), to_integer(offset), - as_limit(limit))); + send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), option_id, + offset, as_limit(limit))); } else if (op == "stoppoll") { string chat_id; string message_id; @@ -3698,10 +3648,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_supergroup_id(supergroup_id), username)); } else if (op == "ssgss") { string supergroup_id; - string sticker_set_id; + int64 sticker_set_id; get_args(args, supergroup_id, sticker_set_id); - send_request(td_api::make_object(as_supergroup_id(supergroup_id), - to_integer(sticker_set_id))); + send_request( + td_api::make_object(as_supergroup_id(supergroup_id), sticker_set_id)); } else if (op == "tsgp") { string supergroup_id; bool is_all_history_available; @@ -3733,10 +3683,9 @@ class CliClient final : public Actor { as_chat_id(chat_id), td_api::make_object(as_location(latitude, longitude), "address"))); } else if (op == "scsmd") { string chat_id; - string slow_mode_delay; + int32 slow_mode_delay; get_args(args, chat_id, slow_mode_delay); - send_request( - td_api::make_object(as_chat_id(chat_id), to_integer(slow_mode_delay))); + send_request(td_api::make_object(as_chat_id(chat_id), slow_mode_delay)); } else if (op == "pcm" || op == "pcms" || op == "pcmo") { string chat_id; string message_id; @@ -3869,18 +3818,17 @@ class CliClient final : public Actor { } else if (op == "rans") { send_request(td_api::make_object()); } else if (op == "rn") { - string group_id; + int32 group_id; string notification_ids; get_args(args, group_id, notification_ids); for (auto notification_id : to_integers(notification_ids)) { - send_request(td_api::make_object(to_integer(group_id), notification_id)); + send_request(td_api::make_object(group_id, notification_id)); } } else if (op == "rng") { - string group_id; - string max_notification_id; + int32 group_id; + int32 max_notification_id; get_args(args, group_id, max_notification_id); - send_request(td_api::make_object(to_integer(group_id), - to_integer(max_notification_id))); + send_request(td_api::make_object(group_id, max_notification_id)); } else if (op == "rcab") { string chat_id = args; send_request(td_api::make_object(as_chat_id(chat_id))); @@ -3930,9 +3878,9 @@ class CliClient final : public Actor { } else if (op == "gstg") { string chat_id; string token; - string x; + int64 x; get_args(args, chat_id, token, x); - send_request(td_api::make_object(as_chat_id(chat_id), token, to_integer(x))); + send_request(td_api::make_object(as_chat_id(chat_id), token, x)); } else if (op == "hsa" || op == "glu" || op == "glua") { send_request(td_api::make_object(as_suggested_action(args))); } else if (op == "glui" || op == "glu" || op == "glua") { @@ -3967,7 +3915,7 @@ class CliClient final : public Actor { op == "editeproxytcp" || op == "tproxy") { string proxy_id; string server; - string port; + int32 port; string user; string password; if (op[0] == 'e') { @@ -3979,20 +3927,19 @@ class CliClient final : public Actor { if (!user.empty() && password.empty()) { type = td_api::make_object(user); } else { - if (port == "80" || port == "8080") { + if (port == 80 || port == 8080) { type = td_api::make_object(user, password, op.back() != 'p'); } else { type = td_api::make_object(user, password); } } - auto port_int = to_integer(port); if (op[0] == 'e') { send_request( - td_api::make_object(as_proxy_id(proxy_id), server, port_int, enable, std::move(type))); + td_api::make_object(as_proxy_id(proxy_id), server, port, enable, std::move(type))); } else if (op == "tproxy") { - send_request(td_api::make_object(server, port_int, std::move(type), 2, 10.0)); + send_request(td_api::make_object(server, port, std::move(type), 2, 10.0)); } else { - send_request(td_api::make_object(server, port_int, enable, std::move(type))); + send_request(td_api::make_object(server, port, enable, std::move(type))); } } else if (op == "gproxy" || op == "gproxies") { send_request(td_api::make_object()); @@ -4056,9 +4003,9 @@ class CliClient final : public Actor { execute(td_api::make_object()); } else if (op == "sltvl" || op == "sltvle" || op == "tag") { string tag; - string level; + int32 level; get_args(args, tag, level); - auto request = td_api::make_object(tag, to_integer(level)); + auto request = td_api::make_object(tag, level); if (op == "sltvl") { send_request(std::move(request)); } else { @@ -4073,10 +4020,10 @@ class CliClient final : public Actor { execute(std::move(request)); } } else if (op == "alog" || op == "aloge") { - string level; + int32 level; string text; get_args(args, level, text); - auto request = td_api::make_object(to_integer(level), text); + auto request = td_api::make_object(level, text); if (op == "alog") { send_request(std::move(request)); } else { @@ -4308,10 +4255,8 @@ void main(int argc, char **argv) { }); options.add_option('W', "", "Preload chat list", [&] { get_chat_list = true; }); options.add_option('n', "disable-network", "Disable network", [&] { disable_network = true; }); - options.add_option('\0', "api-id", "Set Telegram API ID", - [&](Slice parameter) { api_id = to_integer(parameter); }); - options.add_option('\0', "api_id", "Set Telegram API ID", - [&](Slice parameter) { api_id = to_integer(parameter); }); + options.add_checked_option('\0', "api-id", "Set Telegram API ID", OptionParser::parse_integer(api_id)); + options.add_checked_option('\0', "api_id", "Set Telegram API ID", OptionParser::parse_integer(api_id)); options.add_option('\0', "api-hash", "Set Telegram API hash", OptionParser::parse_string(api_hash)); options.add_option('\0', "api_hash", "Set Telegram API hash", OptionParser::parse_string(api_hash)); options.add_check([&] { From 168becf215763d93db48b8b6df2a32ba21e44216 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 20:47:51 +0300 Subject: [PATCH 20/31] tg_cli: simplify SearchQuery parsing. --- td/telegram/cli.cpp | 180 ++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 100 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 3865f9ab1..618815bcb 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -675,9 +675,30 @@ class CliClient final : public Actor { arg = as_bool(args); } - template - void get_args(string &args, Type &arg) { - arg = to_integer(args); + struct SearchQuery { + int32 limit; + string query; + }; + + void get_args(string &args, SearchQuery &arg) { + string limit; + std::tie(limit, arg.query) = split(trim(args)); + auto r_limit = to_integer_safe(limit); + if (r_limit.is_ok() && r_limit.ok() > 0) { + arg.limit = r_limit.ok(); + } else { + arg.limit = 10; + arg.query = std::move(args); + } + args.clear(); + } + + void get_args(string &args, int32 &arg) { + arg = to_integer(args); + } + + void get_args(string &args, int64 &arg) { + arg = to_integer(args); } template @@ -688,18 +709,6 @@ class CliClient final : public Actor { get_args(args, second_arg, other_args...); } - static std::pair get_search_query(string args) { - string limit; - string query; - std::tie(limit, query) = split(trim(args)); - auto r_limit = to_integer_safe(limit); - if (r_limit.is_error() || r_limit.ok() <= 0) { - query = limit + ' ' + query; - r_limit = 10; - } - return {r_limit.ok(), std::move(query)}; - } - void on_result(uint64 generation, uint64 id, td_api::object_ptr result) { auto result_str = to_string(result); if (result != nullptr) { @@ -1848,23 +1857,21 @@ class CliClient final : public Actor { string thread_message_id; string from_message_id; string offset; - int32 limit; + string limit; std::tie(chat_id, args) = split(args); if (op == "gmth") { std::tie(thread_message_id, args) = split(args); } std::tie(from_message_id, args) = split(args); - std::tie(offset, args) = split(args); - std::tie(limit, args) = get_search_query(args); - if (!args.empty()) { - LOG(ERROR) << "Wrong parameters to function getChatHistory specified"; - } else if (op == "gmth") { + std::tie(offset, limit) = split(args); + if (op == "gmth") { send_request(td_api::make_object( as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id), - to_integer(offset), limit)); + to_integer(offset), as_limit(limit))); } else { send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(from_message_id), - to_integer(offset), limit, op == "ghl")); + to_integer(offset), as_limit(limit), + op == "ghl")); } } else if (op == "gcsm") { string chat_id = args; @@ -1910,12 +1917,10 @@ class CliClient final : public Actor { 2147483647)); } else if (op == "SCM") { string chat_id; - int32 limit; - string query; - get_args(args, chat_id, args); - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, nullptr, 0, 0, limit, - nullptr, 0)); + SearchQuery query; + get_args(args, chat_id, query); + send_request(td_api::make_object(as_chat_id(chat_id), query.query, nullptr, 0, 0, + query.limit, nullptr, 0)); } else if (op == "SMME") { string chat_id; string limit; @@ -1955,48 +1960,40 @@ class CliClient final : public Actor { } else if (op == "SearchAudio") { string chat_id; string offset_message_id; - int32 limit; - string query; - get_args(args, chat_id, offset_message_id, args); - std::tie(limit, query) = get_search_query(args); + SearchQuery query; + get_args(args, chat_id, offset_message_id, query); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, + as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, td_api::make_object(), 0)); } else if (op == "SearchDocument") { string chat_id; int64 offset_message_id; - int32 limit; - string query; - get_args(args, chat_id, offset_message_id, args); - std::tie(limit, query) = get_search_query(args); + SearchQuery query; + get_args(args, chat_id, offset_message_id, query); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, offset_message_id, 0, limit, + as_chat_id(chat_id), query.query, nullptr, offset_message_id, 0, query.limit, td_api::make_object(), 0)); } else if (op == "SearchPhoto") { string chat_id; string offset_message_id; - int32 limit; - string query; - get_args(args, chat_id, offset_message_id, args); + SearchQuery query; + get_args(args, chat_id, offset_message_id, query); if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } - std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, + as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, td_api::make_object(), 0)); } else if (op == "SearchChatPhoto") { string chat_id; string offset_message_id; - int32 limit; - string query; - get_args(args, chat_id, offset_message_id, args); + SearchQuery query; + get_args(args, chat_id, offset_message_id, query); if (offset_message_id.empty()) { offset_message_id = "2000000000000000000"; } - std::tie(limit, query) = get_search_query(args); send_request(td_api::make_object( - as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, limit, + as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, td_api::make_object(), 0)); } else if (op == "gcmc") { string chat_id; @@ -2008,15 +2005,9 @@ class CliClient final : public Actor { } else if (op == "gup" || op == "gupp") { string user_id; int32 offset; - int32 limit; - - get_args(args, user_id, offset, args); - std::tie(limit, args) = get_search_query(args); - if (!args.empty()) { - LOG(ERROR) << "Wrong parameters to function getUserProfilePhotos specified"; - } else { - send_request(td_api::make_object(as_user_id(user_id), offset, limit)); - } + string limit; + get_args(args, user_id, offset, limit); + send_request(td_api::make_object(as_user_id(user_id), offset, as_limit(limit))); } else if (op == "dcrm") { string chat_id; string message_id; @@ -2214,15 +2205,13 @@ class CliClient final : public Actor { } else if (op == "gsu") { send_request(td_api::make_object()); } else if (op == "gs") { - int32 limit; - string emoji; - std::tie(limit, emoji) = get_search_query(args); - send_request(td_api::make_object(emoji, limit)); + SearchQuery query; + get_args(args, query); + send_request(td_api::make_object(query.query, query.limit)); } else if (op == "sst") { - int32 limit; - string emoji; - std::tie(limit, emoji) = get_search_query(args); - send_request(td_api::make_object(emoji, limit)); + SearchQuery query; + get_args(args, query); + send_request(td_api::make_object(query.query, query.limit)); } else if (op == "gss") { send_request(td_api::make_object(to_integer(args))); } else if (op == "giss") { @@ -2391,11 +2380,9 @@ class CliClient final : public Actor { } else if (op == "scm") { string chat_id; string filter; - int32 limit; - string query; - get_args(args, chat_id, filter, args); - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, limit, + SearchQuery query; + get_args(args, chat_id, filter, query); + send_request(td_api::make_object(as_chat_id(chat_id), query.query, query.limit, get_chat_members_filter(filter))); } else if (op == "gcm") { string chat_id; @@ -2411,36 +2398,34 @@ class CliClient final : public Actor { string supergroup_id; string message_thread_id; string offset; - int32 limit; - string query; + SearchQuery query; std::tie(supergroup_id, args) = split(args); if (op == "SearchSupergroupMentions") { std::tie(message_thread_id, args) = split(args); } - std::tie(offset, args) = split(args); - std::tie(limit, query) = get_search_query(args); + get_args(args, offset, query); td_api::object_ptr filter; if (op == "GetSupergroupAdministrators") { filter = td_api::make_object(); } else if (op == "GetSupergroupBanned") { - filter = td_api::make_object(query); + filter = td_api::make_object(query.query); } else if (op == "GetSupergroupBots") { filter = td_api::make_object(); } else if (op == "GetSupergroupContacts") { - filter = td_api::make_object(query); + filter = td_api::make_object(query.query); } else if (op == "GetSupergroupMembers") { filter = td_api::make_object(); } else if (op == "GetSupergroupRestricted") { - filter = td_api::make_object(query); + filter = td_api::make_object(query.query); } else if (op == "SearchSupergroupMembers") { - filter = td_api::make_object(query); + filter = td_api::make_object(query.query); } else if (op == "SearchSupergroupMentions") { - filter = - td_api::make_object(query, as_message_thread_id(message_thread_id)); + filter = td_api::make_object(query.query, + as_message_thread_id(message_thread_id)); } send_request(td_api::make_object(as_supergroup_id(supergroup_id), std::move(filter), - to_integer(offset), limit)); + to_integer(offset), query.limit)); } else if (op == "gdialog" || op == "gd") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "open") { @@ -2858,12 +2843,10 @@ class CliClient final : public Actor { string chat_id; string filter; string offset; - int32 limit; - string query; - get_args(args, chat_id, filter, offset, args); - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(as_chat_id(chat_id), query, offset, limit, - as_search_messages_filter(filter))); + SearchQuery query; + get_args(args, chat_id, filter, offset, query); + send_request(td_api::make_object(as_chat_id(chat_id), query.query, offset, + query.limit, as_search_messages_filter(filter))); } else if (op == "ssd") { schedule_date_ = args; } else if (op == "smti") { @@ -3707,15 +3690,13 @@ class CliClient final : public Actor { } else if (op == "spcs") { send_request(td_api::make_object(args)); } else if (op == "sc") { - int32 limit; - string query; - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(query, limit)); + SearchQuery query; + get_args(args, query); + send_request(td_api::make_object(query.query, query.limit)); } else if (op == "scos") { - int32 limit; - string query; - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(query, limit)); + SearchQuery query; + get_args(args, query); + send_request(td_api::make_object(query.query, query.limit)); } else if (op == "scn") { string latitude; string longitude; @@ -3727,10 +3708,9 @@ class CliClient final : public Actor { get_args(args, latitude, longitude); send_request(td_api::make_object(as_location(latitude, longitude))); } else if (op == "sco") { - int32 limit; - string query; - std::tie(limit, query) = get_search_query(args); - send_request(td_api::make_object(query, limit)); + SearchQuery query; + get_args(args, query); + send_request(td_api::make_object(query.query, query.limit)); } else if (op == "arfc") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "rrfc") { From 665446436062c5cf1704c072fb9eacd2f81b9a41 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 20:58:30 +0300 Subject: [PATCH 21/31] tg_cli: use get_args if possible. --- td/telegram/cli.cpp | 51 +++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 618815bcb..744f2cac7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -665,13 +665,13 @@ class CliClient final : public Actor { return transform(transform(full_split(ids_string, get_delimiter(ids_string)), trim), to_integer); } - void get_args(string &args, string &arg) { + static void get_args(string &args, string &arg) { if (&args != &arg) { arg = std::move(args); } } - void get_args(string &args, bool &arg) { + static void get_args(string &args, bool &arg) { arg = as_bool(args); } @@ -680,7 +680,7 @@ class CliClient final : public Actor { string query; }; - void get_args(string &args, SearchQuery &arg) { + static void get_args(string &args, SearchQuery &arg) { string limit; std::tie(limit, arg.query) = split(trim(args)); auto r_limit = to_integer_safe(limit); @@ -693,16 +693,16 @@ class CliClient final : public Actor { args.clear(); } - void get_args(string &args, int32 &arg) { + static void get_args(string &args, int32 &arg) { arg = to_integer(args); } - void get_args(string &args, int64 &arg) { + static void get_args(string &args, int64 &arg) { arg = to_integer(args); } template - void get_args(string &args, FirstType &first_arg, SecondType &second_arg, Types &... other_args) { + static void get_args(string &args, FirstType &first_arg, SecondType &second_arg, Types &... other_args) { string arg; std::tie(arg, args) = split(args); get_args(arg, first_arg); @@ -1174,11 +1174,7 @@ class CliClient final : public Actor { string pinned_chat_ids; string included_chat_ids; string excluded_chat_ids; - std::tie(title, filter) = split(filter); - std::tie(icon_name, filter) = split(filter); - std::tie(pinned_chat_ids, filter) = split(filter); - std::tie(included_chat_ids, filter) = split(filter); - std::tie(excluded_chat_ids, filter) = split(filter); + get_args(filter, title, icon_name, pinned_chat_ids, included_chat_ids, excluded_chat_ids); auto rand_bool = [] { return Random::fast_bool(); @@ -1856,22 +1852,19 @@ class CliClient final : public Actor { string chat_id; string thread_message_id; string from_message_id; - string offset; + int32 offset; string limit; - std::tie(chat_id, args) = split(args); if (op == "gmth") { - std::tie(thread_message_id, args) = split(args); + get_args(args, thread_message_id, args); } - std::tie(from_message_id, args) = split(args); - std::tie(offset, limit) = split(args); + get_args(args, chat_id, from_message_id, offset, limit); if (op == "gmth") { send_request(td_api::make_object( - as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id), - to_integer(offset), as_limit(limit))); + as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id), offset, + as_limit(limit))); } else { send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(from_message_id), - to_integer(offset), as_limit(limit), - op == "ghl")); + offset, as_limit(limit), op == "ghl")); } } else if (op == "gcsm") { string chat_id = args; @@ -2397,14 +2390,13 @@ class CliClient final : public Actor { op == "SearchSupergroupMembers" || op == "SearchSupergroupMentions") { string supergroup_id; string message_thread_id; - string offset; + int32 offset; SearchQuery query; - std::tie(supergroup_id, args) = split(args); if (op == "SearchSupergroupMentions") { - std::tie(message_thread_id, args) = split(args); + get_args(args, message_thread_id, args); } - get_args(args, offset, query); + get_args(args, supergroup_id, offset, query); td_api::object_ptr filter; if (op == "GetSupergroupAdministrators") { filter = td_api::make_object(); @@ -2425,7 +2417,7 @@ class CliClient final : public Actor { as_message_thread_id(message_thread_id)); } send_request(td_api::make_object(as_supergroup_id(supergroup_id), std::move(filter), - to_integer(offset), query.limit)); + offset, query.limit)); } else if (op == "gdialog" || op == "gd") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "open") { @@ -2762,11 +2754,10 @@ class CliClient final : public Actor { string message_thread_id; string reply_to_message_id; string message; - std::tie(chat_id, args) = split(args); if (op == "scdmt") { - std::tie(message_thread_id, args) = split(args); + get_args(args, message_thread_id, args); } - std::tie(reply_to_message_id, message) = split(args); + get_args(args, chat_id, reply_to_message_id, message); td_api::object_ptr draft_message; if (!reply_to_message_id.empty() || !message.empty()) { vector> entities; @@ -2858,7 +2849,7 @@ class CliClient final : public Actor { get_args(args, chat_id, message); if (op == "smr") { - std::tie(reply_to_message_id, message) = split(message); + get_args(message, reply_to_message_id, message); } if (op == "smf") { message = string(5097, 'a'); @@ -2874,7 +2865,7 @@ class CliClient final : public Actor { get_args(args, chat_id, sender_id, message); if (op == "almr") { - std::tie(reply_to_message_id, message) = split(message); + get_args(message, reply_to_message_id, message); } send_request(td_api::make_object( From 4de797e4bd69d190e83fdb20d7ead8b0bb23b1dd Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 21:01:57 +0300 Subject: [PATCH 22/31] tg_cli: use rand_bool everywhere. --- td/telegram/cli.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 744f2cac7..4267db554 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1168,6 +1168,10 @@ class CliClient final : public Actor { return nullptr; } + static bool rand_bool() { + return Random::fast_bool(); + } + td_api::object_ptr as_chat_filter(string filter) const { string title; string icon_name; @@ -1175,11 +1179,6 @@ class CliClient final : public Actor { string included_chat_ids; string excluded_chat_ids; get_args(filter, title, icon_name, pinned_chat_ids, included_chat_ids, excluded_chat_ids); - - auto rand_bool = [] { - return Random::fast_bool(); - }; - return td_api::make_object( title, icon_name, as_chat_ids(pinned_chat_ids), as_chat_ids(included_chat_ids), as_chat_ids(excluded_chat_ids), rand_bool(), rand_bool(), rand_bool(), rand_bool(), rand_bool(), rand_bool(), rand_bool(), rand_bool()); @@ -2562,9 +2561,9 @@ class CliClient final : public Actor { string message_ids; get_args(args, chat_id, from_chat_id, message_ids); 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), default_message_send_options(), op[0] == 'c', - Random::fast_bool())); + send_request( + td_api::make_object(chat, as_chat_id(from_chat_id), as_message_ids(message_ids), + default_message_send_options(), op[0] == 'c', rand_bool())); } else if (op == "resend") { string chat_id; string message_ids; @@ -2586,7 +2585,7 @@ class CliClient final : public Actor { } else if (op == "cc" || op == "CreateCall") { send_request(td_api::make_object( as_user_id(args), td_api::make_object(true, true, 65, 65, vector{"2.6", "3.0"}), - Random::fast_bool())); + rand_bool())); } else if (op == "ac" || op == "AcceptCall") { send_request(td_api::make_object( as_call_id(args), @@ -2597,8 +2596,7 @@ class CliClient final : public Actor { string call_id; bool is_disconnected; get_args(args, call_id, is_disconnected); - send_request( - td_api::make_object(as_call_id(call_id), is_disconnected, 0, Random::fast_bool(), 0)); + send_request(td_api::make_object(as_call_id(call_id), is_disconnected, 0, rand_bool(), 0)); } else if (op == "scr" || op == "SendCallRating") { string call_id; int32 rating; @@ -3099,7 +3097,7 @@ class CliClient final : public Actor { get_args(args, chat_id, from_chat_id, from_message_id); td_api::object_ptr copy_options; if (op == "scopy") { - copy_options = td_api::make_object(true, Random::fast_bool(), as_caption("_as_d")); + copy_options = td_api::make_object(true, rand_bool(), as_caption("_as_d")); } send_message(chat_id, td_api::make_object( @@ -4067,7 +4065,7 @@ class CliClient final : public Actor { } BufferSlice block(it->part_size); FileFd::open(it->source, FileFd::Flags::Read).move_as_ok().pread(block.as_slice(), it->local_size).ensure(); - if (Random::fast_bool()) { + if (rand_bool()) { auto open_flags = FileFd::Flags::Write | (it->local_size ? 0 : FileFd::Flags::Truncate | FileFd::Flags::Create); FileFd::open(it->destination, open_flags).move_as_ok().pwrite(block.as_slice(), it->local_size).ensure(); } else { From d23e6ad352e5d072ade7719a0b930e696f9a07af Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 21:12:09 +0300 Subject: [PATCH 23/31] tg_cli: combine Search* methods. --- td/telegram/cli.cpp | 56 ++++++++++++--------------------------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4267db554..ce9e97b08 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -319,9 +319,8 @@ class CliClient final : public Actor { if (!messages.messages_.empty()) { auto last_message_id = messages.messages_.back()->id_; LOG(ERROR) << (last_message_id >> 20); - send_request(td_api::make_object( - search_chat_id_, "", nullptr, last_message_id, 0, 100, - td_api::make_object(), 0)); + send_request(td_api::make_object(search_chat_id_, "", nullptr, last_message_id, 0, + 100, as_search_messages_filter("pvi"), 0)); } else { search_chat_id_ = 0; } @@ -1078,9 +1077,13 @@ class CliClient final : public Actor { return nullptr; } - static td_api::object_ptr as_search_messages_filter(MutableSlice filter) { + static td_api::object_ptr as_search_messages_filter(Slice filter) { filter = trim(filter); - to_lower_inplace(filter); + string lowered_filter = to_lower(filter); + filter = lowered_filter; + if (begins_with(filter, "search")) { + filter.remove_prefix(6); + } if (filter == "an" || filter == "animation") { return td_api::make_object(); } @@ -1888,9 +1891,8 @@ class CliClient final : public Actor { as_message_thread_id(message_thread_id))); } else if (op == "spvf") { search_chat_id_ = as_chat_id(args); - send_request(td_api::make_object( - search_chat_id_, "", nullptr, 0, 0, 100, td_api::make_object(), - 0)); + send_request(td_api::make_object(search_chat_id_, "", nullptr, 0, 0, 100, + as_search_messages_filter("pvi"), 0)); } else if (op == "Search" || op == "SearchA" || op == "SearchM") { string query; string limit; @@ -1949,44 +1951,14 @@ class CliClient final : public Actor { string limit; get_args(args, chat_id, limit); send_request(td_api::make_object(as_chat_id(chat_id), as_limit(limit))); - } else if (op == "SearchAudio") { + } else if (op == "SearchAudio" || op == "SearchDocument" || op == "SearchPhoto" || op == "SearchChatPhoto") { string chat_id; string offset_message_id; SearchQuery query; get_args(args, chat_id, offset_message_id, query); - send_request(td_api::make_object( - as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, - td_api::make_object(), 0)); - } else if (op == "SearchDocument") { - string chat_id; - int64 offset_message_id; - SearchQuery query; - get_args(args, chat_id, offset_message_id, query); - send_request(td_api::make_object( - as_chat_id(chat_id), query.query, nullptr, offset_message_id, 0, query.limit, - td_api::make_object(), 0)); - } else if (op == "SearchPhoto") { - string chat_id; - string offset_message_id; - SearchQuery query; - get_args(args, chat_id, offset_message_id, query); - if (offset_message_id.empty()) { - offset_message_id = "2000000000000000000"; - } - send_request(td_api::make_object( - as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, - td_api::make_object(), 0)); - } else if (op == "SearchChatPhoto") { - string chat_id; - string offset_message_id; - SearchQuery query; - get_args(args, chat_id, offset_message_id, query); - if (offset_message_id.empty()) { - offset_message_id = "2000000000000000000"; - } - send_request(td_api::make_object( - as_chat_id(chat_id), query.query, nullptr, as_message_id(offset_message_id), 0, query.limit, - td_api::make_object(), 0)); + send_request(td_api::make_object(as_chat_id(chat_id), query.query, nullptr, + as_message_id(offset_message_id), 0, query.limit, + as_search_messages_filter(op), 0)); } else if (op == "gcmc") { string chat_id; string filter; From f56ea080960223f236e619c14c4986ece5349986 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 21:32:21 +0300 Subject: [PATCH 24/31] tg_cli: add get_user_privacy_setting_rules. --- td/telegram/cli.cpp | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ce9e97b08..c4d536b22 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1077,6 +1077,23 @@ class CliClient final : public Actor { return nullptr; } + td_api::object_ptr get_user_privacy_setting_rules(Slice allow, Slice ids) const { + td::vector> rules; + if (allow == "c" || allow == "contacts") { + rules.push_back(td_api::make_object()); + } else if (allow == "users") { + rules.push_back(td_api::make_object(as_user_ids(ids))); + } else if (allow == "chats") { + rules.push_back(td_api::make_object(as_chat_ids(ids))); + } else if (as_bool(allow.str())) { + rules.push_back(td_api::make_object()); + rules.push_back(td_api::make_object()); + } else { + rules.push_back(td_api::make_object()); + } + return td_api::make_object(std::move(rules)); + } + static td_api::object_ptr as_search_messages_filter(Slice filter) { filter = trim(filter); string lowered_filter = to_lower(filter); @@ -1706,7 +1723,6 @@ class CliClient final : public Actor { } else if (op == "gpf") { string chat_id; string message_id; - get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "voi") { @@ -1758,22 +1774,8 @@ class CliClient final : public Actor { string allow; string ids; get_args(args, setting, allow, ids); - - std::vector> rules; - if (allow == "c" || allow == "contacts") { - rules.push_back(td_api::make_object()); - } else if (allow == "users") { - rules.push_back(td_api::make_object(as_user_ids(ids))); - } else if (allow == "chats") { - rules.push_back(td_api::make_object(as_chat_ids(ids))); - } else if (as_bool(allow)) { - rules.push_back(td_api::make_object()); - rules.push_back(td_api::make_object()); - } else { - rules.push_back(td_api::make_object()); - } - send_request(td_api::make_object( - get_user_privacy_setting(setting), td_api::make_object(std::move(rules)))); + send_request(td_api::make_object(get_user_privacy_setting(setting), + get_user_privacy_setting_rules(allow, ids))); } else if (op == "cp" || op == "ChangePhone") { send_request(td_api::make_object(args, nullptr)); } else if (op == "ccpc" || op == "CheckChangePhoneCode") { From 48f51691010b65a1a865e1810dff3d0ef583b229 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 21:45:19 +0300 Subject: [PATCH 25/31] tg_cli: add get_supergroup_members_filter. --- td/telegram/cli.cpp | 86 ++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index c4d536b22..3c6520da8 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1188,6 +1188,49 @@ class CliClient final : public Actor { return nullptr; } + static td_api::object_ptr get_supergroup_members_filter(MutableSlice filter, + string query, + Slice message_thread_id) { + filter = trim(filter); + to_lower_inplace(filter); + if (begins_with(filter, "get")) { + filter.remove_prefix(3); + } + if (begins_with(filter, "search")) { + filter.remove_prefix(6); + } + if (begins_with(filter, "supergroup")) { + filter.remove_prefix(10); + } + if (filter == "administrators") { + return td_api::make_object(); + } + if (filter == "banned") { + return td_api::make_object(query); + } + if (filter == "bots") { + return td_api::make_object(); + } + if (filter == "contacts") { + return td_api::make_object(query); + } + if (filter == "members") { + if (query.empty()) { + return td_api::make_object(); + } else { + return td_api::make_object(query); + } + } + if (filter == "restricted") { + return td_api::make_object(query); + } + if (filter == "nentions") { + return td_api::make_object(query, + as_message_thread_id(message_thread_id)); + } + return nullptr; + } + static bool rand_bool() { return Random::fast_bool(); } @@ -1793,12 +1836,10 @@ class CliClient final : public Actor { string first_name; string last_name; get_args(args, user_id, first_name, last_name); - send_request(td_api::make_object( td_api::make_object(string(), first_name, last_name, string(), as_user_id(user_id)), false)); } else if (op == "spn") { string user_id = args; - send_request(td_api::make_object(as_user_id(user_id))); } else if (op == "ImportContacts" || op == "cic") { vector contacts_str = full_split(args, ';'); @@ -1811,7 +1852,6 @@ class CliClient final : public Actor { std::tie(first_name, last_name) = split(c, ','); contacts.push_back(td_api::make_object(phone_number, first_name, last_name, string(), 0)); } - if (op == "cic") { send_request(td_api::make_object(std::move(contacts))); } else { @@ -1832,7 +1872,6 @@ class CliClient final : public Actor { string offset_order_string; string offset_chat_id; get_args(args, limit, offset_order_string, offset_chat_id); - int64 offset_order; if (offset_order_string.empty()) { offset_order = std::numeric_limits::max(); @@ -1977,7 +2016,6 @@ class CliClient final : public Actor { } else if (op == "dcrm") { string chat_id; string message_id; - get_args(args, chat_id, message_id); send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id))); } else if (op == "glti") { @@ -2042,7 +2080,6 @@ class CliClient final : public Actor { } else { str->value_ = td_api::make_object(); } - send_request(td_api::make_object(language_code, std::move(str))); } else if (op == "dlp") { send_request(td_api::make_object(args)); @@ -2365,32 +2402,13 @@ class CliClient final : public Actor { string message_thread_id; int32 offset; SearchQuery query; - if (op == "SearchSupergroupMentions") { get_args(args, message_thread_id, args); } get_args(args, supergroup_id, offset, query); - td_api::object_ptr filter; - if (op == "GetSupergroupAdministrators") { - filter = td_api::make_object(); - } else if (op == "GetSupergroupBanned") { - filter = td_api::make_object(query.query); - } else if (op == "GetSupergroupBots") { - filter = td_api::make_object(); - } else if (op == "GetSupergroupContacts") { - filter = td_api::make_object(query.query); - } else if (op == "GetSupergroupMembers") { - filter = td_api::make_object(); - } else if (op == "GetSupergroupRestricted") { - filter = td_api::make_object(query.query); - } else if (op == "SearchSupergroupMembers") { - filter = td_api::make_object(query.query); - } else if (op == "SearchSupergroupMentions") { - filter = td_api::make_object(query.query, - as_message_thread_id(message_thread_id)); - } - send_request(td_api::make_object(as_supergroup_id(supergroup_id), std::move(filter), - offset, query.limit)); + send_request(td_api::make_object( + as_supergroup_id(supergroup_id), get_supergroup_members_filter(op, query.query, message_thread_id), offset, + query.limit)); } else if (op == "gdialog" || op == "gd") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "open") { @@ -2818,7 +2836,6 @@ class CliClient final : public Actor { string chat_id; string reply_to_message_id; string message; - get_args(args, chat_id, message); if (op == "smr") { get_args(message, reply_to_message_id, message); @@ -2826,7 +2843,6 @@ class CliClient final : public Actor { if (op == "smf") { message = string(5097, 'a'); } - send_message(chat_id, td_api::make_object(as_formatted_text(message), false, true), op == "sms", false, as_message_id(reply_to_message_id)); } else if (op == "alm" || op == "almr") { @@ -2834,12 +2850,10 @@ class CliClient final : public Actor { string sender_id; string reply_to_message_id; string message; - get_args(args, chat_id, sender_id, message); if (op == "almr") { get_args(message, reply_to_message_id, message); } - send_request(td_api::make_object( as_chat_id(chat_id), as_message_sender(sender_id), as_message_id(reply_to_message_id), false, td_api::make_object(as_formatted_text(message), false, true))); @@ -2847,13 +2861,11 @@ class CliClient final : public Actor { string chat_id; string reply_to_message_id; vector photos; - get_args(args, chat_id, args); if (op == "smapr") { get_args(args, reply_to_message_id, args); } photos = full_split(args); - send_request(td_api::make_object( as_chat_id(chat_id), as_message_thread_id(message_thread_id_), as_message_id(reply_to_message_id), default_message_send_options(), transform(photos, [](const string &photo) { @@ -2864,10 +2876,8 @@ class CliClient final : public Actor { } else if (op == "smad") { string chat_id; vector documents; - get_args(args, chat_id, args); documents = full_split(args); - send_request(td_api::make_object( as_chat_id(chat_id), as_message_thread_id(message_thread_id_), 0, default_message_send_options(), transform(documents, [](const string &document) { @@ -3271,7 +3281,6 @@ class CliClient final : public Actor { } else { sticker_file_ids = to_integers(sticker_file_ids_str); } - send_message(chat_id, td_api::make_object(as_input_file(video_path), nullptr, std::move(sticker_file_ids), 1, 2, 3, true, as_caption(""), op == "svttl" ? 10 : 0)); @@ -3280,7 +3289,6 @@ class CliClient final : public Actor { string video; string thumbnail; get_args(args, chat_id, video, thumbnail); - send_message(chat_id, td_api::make_object( as_input_file(video), as_input_thumbnail(thumbnail), vector(), 0, 0, 0, true, as_caption(""), op == "svtttl" ? 10 : 0)); @@ -3402,7 +3410,6 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id), title)); } else if (op == "scpe") { string chat_id = args; - send_request(td_api::make_object(as_chat_id(chat_id), nullptr)); } else if (op == "scpp") { string chat_id; @@ -3713,7 +3720,6 @@ class CliClient final : public Actor { if (op == "viewt") { get_args(message_ids, message_thread_id, message_ids); } - send_request(td_api::make_object( as_chat_id(chat_id), as_message_thread_id(message_thread_id), as_message_ids(message_ids), true)); } else if (op == "omc") { From 1d155a8492d97e96bec0bec3ab203f59256832fd Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 26 Dec 2020 21:53:39 +0300 Subject: [PATCH 26/31] tg_cli: add get_chat_report_reason. --- td/telegram/cli.cpp | 57 +++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 3c6520da8..8bec04c74 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1312,6 +1312,29 @@ class CliClient final : public Actor { return td_api::make_object(); } + static td_api::object_ptr get_chat_report_reason(MutableSlice reason) { + reason = trim(reason); + if (reason == "spam") { + return td_api::make_object(); + } + if (reason == "violence") { + return td_api::make_object(); + } + if (reason == "porno") { + return td_api::make_object(); + } + if (reason == "ca") { + return td_api::make_object(); + } + if (reason == "copyright") { + return td_api::make_object(); + } + if (reason == "geo" || reason == "location") { + return td_api::make_object(); + } + return td_api::make_object(reason.str()); + } + static td_api::object_ptr get_network_type(MutableSlice type) { type = trim(type); to_lower_inplace(type); @@ -1757,7 +1780,6 @@ class CliClient final : public Actor { string key; string secret; string other_user_ids_str; - get_args(args, endpoint, key, secret, other_user_ids_str); send_request(td_api::make_object( td_api::make_object(endpoint, key, secret), as_user_ids(other_user_ids_str))); @@ -2055,7 +2077,6 @@ class CliClient final : public Actor { "Few", "Many", "Other"))); strings.push_back(td_api::make_object( "DELETED", td_api::make_object())); - send_request(td_api::make_object( as_language_pack_info(language_code, name, native_name), std::move(strings))); } else if (op == "eclpi") { @@ -2753,7 +2774,6 @@ class CliClient final : public Actor { vector> entities; entities.push_back( td_api::make_object(0, 1, td_api::make_object())); - draft_message = td_api::make_object( as_message_id(reply_to_message_id), 0, td_api::make_object(as_formatted_text(message, std::move(entities)), true, @@ -3062,7 +3082,6 @@ class CliClient final : public Actor { string chat_id; string voice_path; get_args(args, chat_id, voice_path); - send_message(chat_id, td_api::make_object(as_input_file(voice_path), 0, "abacaba", as_caption("voice caption"))); } else if (op == "SendContact" || op == "scontact") { @@ -3180,7 +3199,6 @@ class CliClient final : public Actor { string question; get_args(args, chat_id, question, args); auto options = full_split(args); - td_api::object_ptr poll_type; if (op == "squiz") { poll_type = td_api::make_object(narrow_cast(options.size() - 1), @@ -3201,7 +3219,6 @@ class CliClient final : public Actor { } else { sticker_file_ids = to_integers(sticker_file_ids_str); } - send_message(chat_id, td_api::make_object( as_input_file(photo_path), nullptr, std::move(sticker_file_ids), 0, 0, as_caption(op == "spcaption" ? "cap \n\n\n\n tion " : ""), op == "spttl" ? 10 : 0)); @@ -3219,7 +3236,6 @@ class CliClient final : public Actor { string photo_path; string thumbnail_path; get_args(args, chat_id, photo_path, thumbnail_path); - send_message(chat_id, td_api::make_object(as_input_file(photo_path), as_input_thumbnail(thumbnail_path, 90, 89), vector(), 0, 0, as_caption(""), 0)); @@ -3783,29 +3799,11 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id))); } else if (op == "rc") { string chat_id; - string reason_str; + string reason; string message_ids; - get_args(args, chat_id, reason_str, message_ids); - - td_api::object_ptr reason; - if (reason_str == "spam") { - reason = td_api::make_object(); - } else if (reason_str == "violence") { - reason = td_api::make_object(); - } else if (reason_str == "porno") { - reason = td_api::make_object(); - } else if (reason_str == "ca") { - reason = td_api::make_object(); - } else if (reason_str == "copyright") { - reason = td_api::make_object(); - } else if (reason_str == "geo" || reason_str == "location") { - reason = td_api::make_object(); - } else { - reason = td_api::make_object(reason_str); - } - - send_request( - td_api::make_object(as_chat_id(chat_id), std::move(reason), as_message_ids(message_ids))); + get_args(args, chat_id, reason, message_ids); + send_request(td_api::make_object(as_chat_id(chat_id), get_chat_report_reason(reason), + as_message_ids(message_ids))); } else if (op == "gcsu") { string chat_id; string parameters; @@ -3849,7 +3847,6 @@ class CliClient final : public Actor { string user_id; string message_ids; get_args(args, supergroup_id, user_id, message_ids); - send_request(td_api::make_object(as_supergroup_id(supergroup_id), as_user_id(user_id), as_message_ids(message_ids))); } else if (op == "gdiff") { From 1f9d173afb81cf4389b52a211a960747c9b96f99 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 00:30:27 +0300 Subject: [PATCH 27/31] Automatically check whether group call is still joined. --- td/generate/scheme/td_api.tl | 3 -- td/generate/scheme/td_api.tlo | Bin 191552 -> 191448 bytes td/telegram/GroupCallManager.cpp | 87 +++++++++++++++++++++++-------- td/telegram/GroupCallManager.h | 10 +++- td/telegram/Td.cpp | 6 --- td/telegram/Td.h | 2 - td/telegram/cli.cpp | 2 - 7 files changed, 72 insertions(+), 38 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index be6b7afda..1deba5c51 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4394,9 +4394,6 @@ setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:B //@group_call_id Group call identifier @user_id User identifier @is_muted Pass true if the user must be muted and false otherwise toggleGroupCallParticipantIsMuted group_call_id:int32 user_id:int32 is_muted:Bool = Ok; -//@description Checks whether a group call is still joined. Should be called every 10 seconds when tgcalls notifies about lost connection with the server @group_call_id Group call identifier -checkGroupCallIsJoined group_call_id:int32 = Ok; - //@description Loads more group call participants. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded //@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined //@limit Maximum number of participants to load diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index c92950cd4f574c4b75076ffba2bd597db5e70f80..f397f69f386a30751530f7bfedfcd7e2685bcaf5 100644 GIT binary patch delta 27 jcmX?bgZsvH?uHh|Elf4aj1#ukDl^>|-hRZKsb&iRs6`8S delta 60 zcmca{o%_HI?uHh|Elf4aj1#xlDl^>|maY&wnIx8+k(!+CUX)*2;GCF~<5}#LpP84M QGCg}TlkfHzbEcXt0NSz_cK`qY diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 379c0ea27..8dfa243c8 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -440,6 +440,9 @@ struct GroupCallManager::PendingJoinRequest { }; GroupCallManager::GroupCallManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { + check_group_call_is_joined_timeout_.set_callback(on_check_group_call_is_joined_timeout_callback); + check_group_call_is_joined_timeout_.set_callback_data(static_cast(this)); + pending_send_speaking_action_timeout_.set_callback(on_pending_send_speaking_action_timeout_callback); pending_send_speaking_action_timeout_.set_callback_data(static_cast(this)); @@ -456,6 +459,45 @@ void GroupCallManager::tear_down() { parent_.reset(); } +void GroupCallManager::on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, + int64 group_call_id_int) { + if (G()->close_flag()) { + return; + } + + auto group_call_manager = static_cast(group_call_manager_ptr); + send_closure_later(group_call_manager->actor_id(group_call_manager), + &GroupCallManager::on_check_group_call_is_joined_timeout, + GroupCallId(narrow_cast(group_call_id_int))); +} + +void GroupCallManager::on_check_group_call_is_joined_timeout(GroupCallId group_call_id) { + if (G()->close_flag()) { + return; + } + + LOG(INFO) << "Receive check group call is_joined timeout in " << group_call_id; + auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok(); + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + if (!group_call->is_joined || check_group_call_is_joined_timeout_.has_timeout(group_call_id.get())) { + return; + } + + auto source = group_call->source; + auto promise = + PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source](Result &&result) mutable { + if (result.is_error() && result.error().message() == "GROUP_CALL_JOIN_MISSING") { + send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true); + result = Unit(); + } + send_closure(actor_id, &GroupCallManager::finish_check_group_call_is_joined, input_group_call_id, source, + std::move(result)); + }); + td_->create_handler(std::move(promise))->send(input_group_call_id, source); +} + void GroupCallManager::on_pending_send_speaking_action_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int) { if (G()->close_flag()) { @@ -779,6 +821,21 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i } } +void GroupCallManager::finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 source, + Result &&result) { + LOG(INFO) << "Finish check group call is_joined for " << input_group_call_id; + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + if (!group_call->is_joined || check_group_call_is_joined_timeout_.has_timeout(group_call->group_call_id.get()) || + group_call->source != source) { + return; + } + + int32 next_timeout = result.is_ok() ? CHECK_GROUP_CALL_IS_JOINED_TIMEOUT : 1; + check_group_call_is_joined_timeout_.set_timeout_in(group_call->group_call_id.get(), next_timeout); +} + bool GroupCallManager::need_group_call_participants(InputGroupCallId input_group_call_id) const { auto *group_call = get_group_call(input_group_call_id); if (group_call == nullptr || !group_call->is_inited || !group_call->is_active) { @@ -1586,6 +1643,8 @@ bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_ group_call->joined_date = G()->unix_time(); group_call->source = it->second->source; it->second->promise.set_value(result.move_as_ok()); + check_group_call_is_joined_timeout_.set_timeout_in(group_call->group_call_id.get(), + CHECK_GROUP_CALL_IS_JOINED_TIMEOUT); need_update = true; } pending_join_requests_.erase(it); @@ -1661,6 +1720,10 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_ } else { recursive = true; } + if (source != group_call->source && !recursive && is_speaking && + check_group_call_is_joined_timeout_.has_timeout(group_call_id.get())) { + check_group_call_is_joined_timeout_.set_timeout_in(group_call_id.get(), CHECK_GROUP_CALL_IS_JOINED_TIMEOUT); + } UserId user_id = set_group_call_participant_is_speaking_by_source(input_group_call_id, source, is_speaking, date); if (!user_id.is_valid()) { if (!recursive) { @@ -1725,29 +1788,6 @@ void GroupCallManager::toggle_group_call_participant_is_muted(GroupCallId group_ td_->create_handler(std::move(promise))->send(input_group_call_id, user_id, is_muted); } -void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Promise &&promise) { - TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); - - auto *group_call = get_group_call(input_group_call_id); - if (group_call == nullptr || !group_call->is_inited) { - return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING")); - } - if (!group_call->is_active || !group_call->is_joined || group_call->joined_date > G()->unix_time() - 8) { - return promise.set_value(Unit()); - } - auto source = group_call->source; - - auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source, - promise = std::move(promise)](Result &&result) mutable { - if (result.is_error() && result.error().message() == "GROUP_CALL_JOIN_MISSING") { - send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true); - result = Unit(); - } - promise.set_result(std::move(result)); - }); - td_->create_handler(std::move(query_promise))->send(input_group_call_id, source); -} - void GroupCallManager::load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise &&promise) { if (limit <= 0) { return promise.set_error(Status::Error(400, "Parameter limit must be positive")); @@ -1816,6 +1856,7 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_ group_call->source = 0; group_call->loaded_all_participants = false; group_call->version = -1; + check_group_call_is_joined_timeout_.cancel_timeout(group_call->group_call_id.get()); try_clear_group_call_participants(get_input_group_call_id(group_call->group_call_id).ok()); } diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index fbd0dca24..46d325f0f 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -62,8 +62,6 @@ class GroupCallManager : public Actor { void toggle_group_call_participant_is_muted(GroupCallId group_call_id, UserId user_id, bool is_muted, Promise &&promise); - void check_group_call_is_joined(GroupCallId group_call_id, Promise &&promise); - void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise &&promise); void leave_group_call(GroupCallId group_call_id, Promise &&promise); @@ -92,9 +90,14 @@ class GroupCallManager : public Actor { struct PendingJoinRequest; static constexpr int32 RECENT_SPEAKER_TIMEOUT = 5 * 60; + static constexpr int32 CHECK_GROUP_CALL_IS_JOINED_TIMEOUT = 10; void tear_down() override; + static void on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int); + + void on_check_group_call_is_joined_timeout(GroupCallId group_call_id); + static void on_pending_send_speaking_action_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int); void on_send_speaking_action_timeout(GroupCallId group_call_id); @@ -125,6 +128,8 @@ class GroupCallManager : public Actor { void finish_get_group_call(InputGroupCallId input_group_call_id, Result> &&result); + void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 source, Result &&result); + bool need_group_call_participants(InputGroupCallId input_group_call_id) const; bool process_pending_group_call_participant_updates(InputGroupCallId input_group_call_id); @@ -219,6 +224,7 @@ class GroupCallManager : public Actor { std::unordered_map, InputGroupCallIdHash> pending_join_requests_; uint64 join_group_request_generation_ = 0; + MultiTimeout check_group_call_is_joined_timeout_{"CheckGroupCallIsJoinedTimeout"}; MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"}; MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"}; MultiTimeout sync_participants_timeout_{"SyncParticipantsTimeout"}; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 5b31c42c1..42c49f5bf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6074,12 +6074,6 @@ void Td::on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted & GroupCallId(request.group_call_id_), UserId(request.user_id_), request.is_muted_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::checkGroupCallIsJoined &request) { - CHECK_IS_USER(); - CREATE_OK_REQUEST_PROMISE(); - group_call_manager_->check_group_call_is_joined(GroupCallId(request.group_call_id_), std::move(promise)); -} - void Td::on_request(uint64 id, const td_api::loadGroupCallParticipants &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index da095a865..d5e28b22e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -706,8 +706,6 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted &request); - void on_request(uint64 id, const td_api::checkGroupCallIsJoined &request); - void on_request(uint64 id, const td_api::loadGroupCallParticipants &request); void on_request(uint64 id, const td_api::leaveGroupCall &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8bec04c74..e031ae843 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2664,8 +2664,6 @@ class CliClient final : public Actor { get_args(args, group_call_id, user_id, is_muted); send_request(td_api::make_object(as_group_call_id(group_call_id), as_user_id(user_id), is_muted)); - } else if (op == "cgcij") { - send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "lgcp") { string group_call_id; string limit; From 2c8cfc561c8e724ef521f2b08cfed00c00be0ab2 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 14:19:29 +0300 Subject: [PATCH 28/31] Add is_speaking flag for recent speakers. --- td/generate/scheme/td_api.tl | 7 ++-- td/generate/scheme/td_api.tlo | Bin 191448 -> 191624 bytes td/telegram/GroupCallManager.cpp | 58 ++++++++++++++++++------------- td/telegram/GroupCallManager.h | 11 +++--- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 1deba5c51..1fe948319 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2066,6 +2066,9 @@ callStateDiscarded reason:CallDiscardReason need_rating:Bool need_debug_informat callStateError error:error = CallState; +//@description Describes a recently speaking user in a group call @user_id User identifier @is_speaking True, is the user has spoken recently +groupCallRecentSpeaker user_id:int32 is_speaking:Bool = GroupCallRecentSpeaker; + //@description Describes a group call //@id Group call identifier //@is_active True, if the call is active @@ -2075,11 +2078,11 @@ callStateError error:error = CallState; //@can_be_managed True, if the current user can manage the group call //@participant_count Number of participants in the group call //@loaded_all_participants True, if all group call participants are loaded -//@recent_speaker_user_ids Identifiers of recently speaking users in the group call +//@recent_speakers Recently speaking users in the group call //@mute_new_participants True, if only group call administrators can unmute new participants //@allowed_change_mute_new_participants True, if group call administrators can enable or disable mute_new_participants setting //@duration Call duration; for ended calls only -groupCall id:int32 is_active:Bool is_joined:Bool need_rejoin:Bool can_unmute_self:Bool can_be_managed:Bool participant_count:int32 loaded_all_participants:Bool recent_speaker_user_ids:vector mute_new_participants:Bool allowed_change_mute_new_participants:Bool duration:int32 = GroupCall; +groupCall id:int32 is_active:Bool is_joined:Bool need_rejoin:Bool can_unmute_self:Bool can_be_managed:Bool participant_count:int32 loaded_all_participants:Bool recent_speakers:vector mute_new_participants:Bool allowed_change_mute_new_participants:Bool duration:int32 = GroupCall; //@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index f397f69f386a30751530f7bfedfcd7e2685bcaf5..d11f1af51cd6e91cd29e9aed3f52736c1fc007fa 100644 GIT binary patch delta 241 zcmca{ox9^EH}9j_`c@23puUlpTZrY+k^1+WWrQLaC3#}+nToj=<(C#XC+6e?r6#B5 zl>`^0CT35b$S%FPMEHq3W8&sWcAU&MvFqI4pApXr`LOwi`3%!&#H|&sLyIx68{il$&jK=j@`asCAU0O)+Q6y+wh?X)l8vcF3?RAb0hgF`rq4Lbqyg65EOTJH l%mKzNreGtcZ@9szu>H$d#*8vBfAWR`3ov8*oE#>bdH|&BV;ukh delta 150 zcmeCU$$jHGH}9j_`c@23ptg~hTZlzwA% zTHu_Rlf%FOR@Jk^fst3dC^b1XuOz;>AT=?2vSFq9WR6`kAf_zYwSl$y#)0iO4lu4T g1q)42xXGxneaSb*j4}vcAeYGk%-Zgg%Vbjz09jEx9smFU diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 8dfa243c8..546c9a1f1 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -429,7 +429,7 @@ struct GroupCallManager::GroupCallParticipants { struct GroupCallManager::GroupCallRecentSpeakers { vector> users; // user + time; sorted by time bool is_changed = false; - vector last_sent_user_ids; + vector> last_sent_users; }; struct GroupCallManager::PendingJoinRequest { @@ -552,8 +552,8 @@ void GroupCallManager::on_recent_speaker_update_timeout(GroupCallId group_call_i LOG(INFO) << "Receive recent speaker update timeout in " << group_call_id; auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok(); - get_recent_speaker_user_ids(get_group_call(input_group_call_id), - false); // will update the list and send updateGroupCall if needed + get_recent_speakers(get_group_call(input_group_call_id), + false); // will update the list and send updateGroupCall if needed } void GroupCallManager::on_sync_participants_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int) { @@ -730,7 +730,7 @@ void GroupCallManager::get_group_call(GroupCallId group_call_id, auto group_call = get_group_call(input_group_call_id); if (group_call != nullptr && group_call->is_inited) { - return promise.set_value(get_group_call_object(group_call, get_recent_speaker_user_ids(group_call, false))); + return promise.set_value(get_group_call_object(group_call, get_recent_speakers(group_call, false))); } reload_group_call(input_group_call_id, std::move(promise)); @@ -816,7 +816,7 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i CHECK(group_call != nullptr && group_call->is_inited); for (auto &promise : promises) { if (promise) { - promise.set_value(get_group_call_object(group_call, get_recent_speaker_user_ids(group_call, false))); + promise.set_value(get_group_call_object(group_call, get_recent_speakers(group_call, false))); } } } @@ -2231,64 +2231,74 @@ void GroupCallManager::update_group_call_dialog(const GroupCall *group_call, con group_call->participant_count == 0, source); } -vector GroupCallManager::get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update) { +vector> GroupCallManager::get_recent_speakers( + const GroupCall *group_call, bool for_update) { CHECK(group_call != nullptr && group_call->is_inited); - vector recent_speaker_user_ids; auto recent_speakers_it = group_call_recent_speakers_.find(group_call->group_call_id); if (recent_speakers_it == group_call_recent_speakers_.end()) { - return recent_speaker_user_ids; + return Auto(); } auto *recent_speakers = recent_speakers_it->second.get(); CHECK(recent_speakers != nullptr); LOG(INFO) << "Found " << recent_speakers->users.size() << " recent speakers in " << group_call->group_call_id << " from " << group_call->dialog_id; - while (!recent_speakers->users.empty() && - recent_speakers->users.back().second < G()->unix_time() - RECENT_SPEAKER_TIMEOUT) { + auto now = G()->unix_time(); + while (!recent_speakers->users.empty() && recent_speakers->users.back().second < now - RECENT_SPEAKER_TIMEOUT) { recent_speakers->users.pop_back(); } + vector> recent_speaker_users; for (auto &recent_speaker : recent_speakers->users) { - recent_speaker_user_ids.push_back(recent_speaker.first.get()); + recent_speaker_users.emplace_back(recent_speaker.first, recent_speaker.second > now - 5); } if (recent_speakers->is_changed) { recent_speakers->is_changed = false; recent_speaker_update_timeout_.cancel_timeout(group_call->group_call_id.get()); } - if (!recent_speakers->users.empty()) { - auto next_timeout = recent_speakers->users.back().second + RECENT_SPEAKER_TIMEOUT - G()->unix_time() + 1; + if (!recent_speaker_users.empty()) { + auto next_timeout = recent_speakers->users.back().second + RECENT_SPEAKER_TIMEOUT - now + 1; + if (recent_speaker_users[0].second) { // if someone is speaking, recheck in 1 second + next_timeout = 1; + } recent_speaker_update_timeout_.add_timeout_in(group_call->group_call_id.get(), next_timeout); } - if (recent_speakers->last_sent_user_ids != recent_speaker_user_ids) { - recent_speakers->last_sent_user_ids = recent_speaker_user_ids; + auto get_result = [recent_speaker_users] { + return transform(recent_speaker_users, [](const std::pair &recent_speaker_user) { + return td_api::make_object(recent_speaker_user.first.get(), + recent_speaker_user.second); + }); + }; + if (recent_speakers->last_sent_users != recent_speaker_users) { + recent_speakers->last_sent_users = std::move(recent_speaker_users); if (!for_update) { // the change must be received through update first - send_update_group_call(group_call, "get_recent_speaker_user_ids"); + send_closure(G()->td(), &Td::send_update, get_update_group_call_object(group_call, get_result())); } } - return recent_speaker_user_ids; + + return get_result(); } -tl_object_ptr GroupCallManager::get_group_call_object(const GroupCall *group_call, - vector recent_speaker_user_ids) const { +tl_object_ptr GroupCallManager::get_group_call_object( + const GroupCall *group_call, vector> recent_speakers) const { CHECK(group_call != nullptr); CHECK(group_call->is_inited); return td_api::make_object( group_call->group_call_id.get(), group_call->is_active, group_call->is_joined, group_call->need_rejoin, group_call->can_self_unmute, group_call->can_be_managed, group_call->participant_count, - group_call->loaded_all_participants, std::move(recent_speaker_user_ids), group_call->mute_new_participants, + group_call->loaded_all_participants, std::move(recent_speakers), group_call->mute_new_participants, group_call->allowed_change_mute_new_participants, group_call->duration); } tl_object_ptr GroupCallManager::get_update_group_call_object( - const GroupCall *group_call, vector recent_speaker_user_ids) const { - return td_api::make_object( - get_group_call_object(group_call, std::move(recent_speaker_user_ids))); + const GroupCall *group_call, vector> recent_speakers) const { + return td_api::make_object(get_group_call_object(group_call, std::move(recent_speakers))); } tl_object_ptr GroupCallManager::get_update_group_call_participant_object( @@ -2300,7 +2310,7 @@ tl_object_ptr GroupCallManager::get_update_g void GroupCallManager::send_update_group_call(const GroupCall *group_call, const char *source) { LOG(INFO) << "Send update about " << group_call->group_call_id << " from " << source; send_closure(G()->td(), &Td::send_update, - get_update_group_call_object(group_call, get_recent_speaker_user_ids(group_call, true))); + get_update_group_call_object(group_call, get_recent_speakers(group_call, true))); } void GroupCallManager::send_update_group_call_participant(GroupCallId group_call_id, diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index 46d325f0f..468fefaa7 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -186,13 +186,14 @@ class GroupCallManager : public Actor { void update_group_call_dialog(const GroupCall *group_call, const char *source); - vector get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update); + vector> get_recent_speakers(const GroupCall *group_call, + bool for_update); - tl_object_ptr get_update_group_call_object(const GroupCall *group_call, - vector recent_speaker_user_ids) const; + tl_object_ptr get_update_group_call_object( + const GroupCall *group_call, vector> recent_speakers) const; - tl_object_ptr get_group_call_object(const GroupCall *group_call, - vector recent_speaker_user_ids) const; + tl_object_ptr get_group_call_object( + const GroupCall *group_call, vector> recent_speakers) const; tl_object_ptr get_update_group_call_participant_object( GroupCallId group_call_id, const GroupCallParticipant &participant); From 5f02a34c34aadf188efa6511f1ae81100fb74184 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 15:19:56 +0300 Subject: [PATCH 29/31] Don't hide reply info for yet unsent messages. --- td/telegram/MessagesManager.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 7a57c2762..fffef3bc9 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -6632,7 +6632,10 @@ bool MessagesManager::is_active_message_reply_info(DialogId dialog_id, const Mes bool MessagesManager::is_visible_message_reply_info(DialogId dialog_id, const Message *m) const { CHECK(m != nullptr); - if (!m->message_id.is_valid() || !m->message_id.is_server()) { + if (!m->message_id.is_valid()) { + return false; + } + if (!m->message_id.is_server() && !m->message_id.is_yet_unsent()) { return false; } if (is_broadcast_channel(dialog_id) && (m->had_reply_markup || m->reply_markup != nullptr)) { @@ -16255,6 +16258,9 @@ Result MessagesManager::get_top_thread_full_message_id(DialogId d if (!is_visible_message_reply_info(dialog_id, m)) { return Status::Error(400, "Message has no comments"); } + if (m->message_id.is_yet_unsent()) { + return Status::Error(400, "Message is not sent yet"); + } return FullMessageId{DialogId(m->reply_info.channel_id), m->linked_top_thread_message_id}; } else { if (!m->top_thread_message_id.is_valid()) { @@ -16735,7 +16741,7 @@ Result> MessagesManager::get_message_link(FullMessageId return Status::Error(400, "Message not found"); } if (m->message_id.is_yet_unsent()) { - return Status::Error(400, "Message is yet unsent"); + return Status::Error(400, "Message is not sent yet"); } if (m->message_id.is_scheduled()) { return Status::Error(400, "Message is scheduled"); @@ -16834,7 +16840,7 @@ string MessagesManager::get_message_embedding_code(FullMessageId full_message_id return {}; } if (m->message_id.is_yet_unsent()) { - promise.set_error(Status::Error(400, "Message is yet unsent")); + promise.set_error(Status::Error(400, "Message is not sent yet")); return {}; } if (m->message_id.is_scheduled()) { From 6af4338f8bdb522068285a9e6a5df608dd1f232a Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 16:21:39 +0300 Subject: [PATCH 30/31] Add MessagesManager::update_forward_count. --- td/telegram/MessagesManager.cpp | 42 ++++++++++++++++++--------------- td/telegram/MessagesManager.h | 2 ++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index fffef3bc9..f525bd381 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -9136,12 +9136,10 @@ void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_ set_dialog_last_new_message_id( d, last_added_message_id.is_valid() ? last_added_message_id : last_received_message_id, "on_get_history"); } - if (last_added_message_id.is_valid()) { - if (last_added_message_id > d->last_message_id) { - CHECK(d->last_new_message_id.is_valid()); - set_dialog_last_message_id(d, last_added_message_id, "on_get_history"); - send_update_chat_last_message(d, "on_get_history"); - } + if (last_added_message_id.is_valid() && last_added_message_id > d->last_message_id) { + CHECK(d->last_new_message_id.is_valid()); + set_dialog_last_message_id(d, last_added_message_id, "on_get_history"); + send_update_chat_last_message(d, "on_get_history"); } } @@ -13163,14 +13161,6 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f CHECK(d != nullptr); - if (is_sent_message) { - try_add_active_live_location(dialog_id, m); - - // add_message_to_dialog will not update counts, because need_update == false - update_message_count_by_index(d, +1, m); - update_reply_count_by_message(d, +1, m); - } - auto pcc_it = pending_created_dialogs_.find(dialog_id); if (from_update && pcc_it != pending_created_dialogs_.end()) { pcc_it->second.set_value(Unit()); @@ -13182,6 +13172,14 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f send_update_new_message(d, m); } + if (is_sent_message) { + try_add_active_live_location(dialog_id, m); + + // add_message_to_dialog will not update counts, because need_update == false + update_message_count_by_index(d, +1, m); + update_reply_count_by_message(d, +1, m); + } + if (dialog_id.get_type() == DialogType::Channel && !have_input_peer(dialog_id, AccessRights::Read)) { auto p = delete_message(d, message_id, false, &need_update_dialog_pos, "get a message in inaccessible chat"); CHECK(p.get() == m); @@ -31973,11 +31971,8 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } } - if (!td_->auth_manager_->is_bot() && from_update && m->forward_info != nullptr && - m->forward_info->sender_dialog_id.is_valid() && m->forward_info->message_id.is_valid() && - (!is_discussion_message(dialog_id, m) || m->forward_info->sender_dialog_id != m->forward_info->from_dialog_id || - m->forward_info->message_id != m->forward_info->from_message_id)) { - update_forward_count(m->forward_info->sender_dialog_id, m->forward_info->message_id, m->date); + if (*need_update) { + update_forward_count(dialog_id, m); } return result_message; @@ -35351,6 +35346,15 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) { } } +void MessagesManager::update_forward_count(DialogId dialog_id, const Message *m) { + if (!td_->auth_manager_->is_bot() && m->forward_info != nullptr && + m->forward_info->sender_dialog_id.is_valid() && m->forward_info->message_id.is_valid() && + (!is_discussion_message(dialog_id, m) || m->forward_info->sender_dialog_id != m->forward_info->from_dialog_id || + m->forward_info->message_id != m->forward_info->from_message_id)) { + update_forward_count(m->forward_info->sender_dialog_id, m->forward_info->message_id, m->date); + } +} + void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message_id, int32 update_date) { CHECK(!td_->auth_manager_->is_bot()); Dialog *d = get_dialog(dialog_id); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 508061ba1..f9c695d03 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -2916,6 +2916,8 @@ class MessagesManager : public Actor { void update_top_dialogs(DialogId dialog_id, const Message *m); + void update_forward_count(DialogId dialog_id, const Message *m); + void update_forward_count(DialogId dialog_id, MessageId message_id, int32 update_date); void try_hide_distance(DialogId dialog_id, const Message *m); From 8139e0d560b25cd2827fb0473e5726319998c10f Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 28 Dec 2020 16:58:50 +0300 Subject: [PATCH 31/31] Update forward_count and thread reply_info only after updateNewMessage is sent. --- td/telegram/MessagesManager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index f525bd381..65923ea70 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -13177,7 +13177,11 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f // add_message_to_dialog will not update counts, because need_update == false update_message_count_by_index(d, +1, m); + } + + if (is_sent_message || need_update) { update_reply_count_by_message(d, +1, m); + update_forward_count(dialog_id, m); } if (dialog_id.get_type() == DialogType::Channel && !have_input_peer(dialog_id, AccessRights::Read)) { @@ -28032,6 +28036,8 @@ FullMessageId MessagesManager::on_send_message_success(int64 random_id, MessageI send_update_chat_last_message(d, "on_send_message_success"); } try_add_active_live_location(dialog_id, m); + update_reply_count_by_message(d, +1, m); + update_forward_count(dialog_id, m); being_readded_message_id_ = FullMessageId(); return {dialog_id, new_message_id}; } @@ -31788,7 +31794,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } if (*need_update) { update_message_count_by_index(d, +1, message.get()); - update_reply_count_by_message(d, +1, message.get()); } if (auto_attach && message_id > d->last_message_id && message_id >= d->last_new_message_id) { set_dialog_last_message_id(d, message_id, "add_message_to_dialog"); @@ -31971,9 +31976,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } } - if (*need_update) { - update_forward_count(dialog_id, m); - } return result_message; } @@ -35347,8 +35349,8 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) { } void MessagesManager::update_forward_count(DialogId dialog_id, const Message *m) { - if (!td_->auth_manager_->is_bot() && m->forward_info != nullptr && - m->forward_info->sender_dialog_id.is_valid() && m->forward_info->message_id.is_valid() && + if (!td_->auth_manager_->is_bot() && m->forward_info != nullptr && m->forward_info->sender_dialog_id.is_valid() && + m->forward_info->message_id.is_valid() && (!is_discussion_message(dialog_id, m) || m->forward_info->sender_dialog_id != m->forward_info->from_dialog_id || m->forward_info->message_id != m->forward_info->from_message_id)) { update_forward_count(m->forward_info->sender_dialog_id, m->forward_info->message_id, m->date);