From 92327f1fe790c93bef9e83c3faa7596c93c934a6 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 17:02:09 +0300 Subject: [PATCH 01/29] Ignore checkGroupCallIsJoined requests first 10 seconds. --- td/telegram/GroupCallManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 9c85db2d6..03c5cbf18 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -414,6 +414,7 @@ struct GroupCallManager::GroupCall { int32 version = -1; int32 duration = 0; int32 source = 0; + int32 joined_date = 0; }; struct GroupCallManager::GroupCallParticipants { @@ -1403,6 +1404,7 @@ bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_ auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr); group_call->is_joined = true; + group_call->joined_date = G()->unix_time(); group_call->source = it->second->source; it->second->promise.set_value(result.move_as_ok()); need_update = true; @@ -1548,7 +1550,7 @@ void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Pro 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) { + if (!group_call->is_active || !group_call->is_joined || group_call->joined_date > G()->unix_time() - 10) { return promise.set_value(Unit()); } auto source = group_call->source; @@ -1624,6 +1626,7 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call) { group_call->is_joined = false; group_call->is_speaking = false; group_call->can_self_unmute = false; + group_call->joined_date = 0; group_call->source = 0; group_call->loaded_all_participants = false; group_call->version = -1; From 415a64ff24a33bad766c8b44e4344ad67d5482b3 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 17:43:34 +0300 Subject: [PATCH 02/29] Allow loading channel participants without bot info. --- td/telegram/ContactsManager.cpp | 8 ++++++-- td/telegram/ContactsManager.h | 4 ++-- td/telegram/MessagesManager.cpp | 6 +++--- td/telegram/MessagesManager.h | 4 ++-- td/telegram/Td.cpp | 6 +++--- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index c3e40f4f6..872851ee6 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -13492,7 +13492,8 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, std::pair> ContactsManager::get_channel_participants( ChannelId channel_id, const tl_object_ptr &filter, const string &additional_query, - int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force, Promise &&promise) { + int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool without_bot_info, bool force, + Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = received_channel_participants_.find(random_id); @@ -13537,7 +13538,10 @@ std::pair> ContactsManager::get_channel_partici } auto channel_full = get_channel_full_force(channel_id, "get_channel_participants"); - if (channel_full == nullptr || (!force && channel_full->is_expired())) { + if (td_->auth_manager_->is_bot()) { + without_bot_info = true; + } + if (!without_bot_info && (channel_full == nullptr || (!force && channel_full->is_expired()))) { if (force) { LOG(ERROR) << "Can't find cached ChannelFull"; } else { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 9bee0274c..13bbe9034 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -509,8 +509,8 @@ class ContactsManager : public Actor { std::pair> get_channel_participants( ChannelId channel_id, const tl_object_ptr &filter, - const string &additional_query, int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force, - Promise &&promise); + const string &additional_query, int32 offset, int32 limit, int32 additional_limit, int64 &random_id, + bool without_bot_info, bool force, Promise &&promise); void send_get_channel_participants_query(ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, int64 random_id, Promise &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 20cc4c366..01a47336d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -30478,8 +30478,8 @@ std::pair> MessagesManager::search_private_chat } std::pair> MessagesManager::search_dialog_participants( - DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, int64 &random_id, bool force, - Promise &&promise) { + DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, int64 &random_id, + bool without_bot_info, bool force, Promise &&promise) { LOG(INFO) << "Receive searchChatMembers request to search for " << query << " in " << dialog_id; if (!have_dialog_force(dialog_id)) { promise.set_error(Status::Error(3, "Chat not found")); @@ -30548,7 +30548,7 @@ std::pair> MessagesManager::search_dialog_parti return td_->contacts_manager_->get_channel_participants(dialog_id.get_channel_id(), request_filter, additional_query, 0, limit, additional_limit, random_id, - force, std::move(promise)); + without_bot_info, force, std::move(promise)); } case DialogType::SecretChat: { promise.set_value(Unit()); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index d02adddfb..2c5e88851 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -534,8 +534,8 @@ class MessagesManager : public Actor { std::pair> search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, - int64 &random_id, bool force, - Promise &&promise); + int64 &random_id, bool without_bot_info, + bool force, Promise &&promise); vector get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 615e9be9a..b90d74b29 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1970,7 +1970,7 @@ class SearchChatMembersRequest : public RequestActor<> { void do_run(Promise &&promise) override { participants_ = td->messages_manager_->search_dialog_participants(dialog_id_, query_, limit_, filter_, random_id_, - get_tries() < 3, std::move(promise)); + false, get_tries() < 3, std::move(promise)); } void do_send_result() override { @@ -2286,8 +2286,8 @@ class GetSupergroupMembersRequest : public RequestActor<> { std::pair> participants_; void do_run(Promise &&promise) override { - participants_ = td->contacts_manager_->get_channel_participants(channel_id_, filter_, string(), offset_, limit_, -1, - random_id_, get_tries() < 3, std::move(promise)); + participants_ = td->contacts_manager_->get_channel_participants( + channel_id_, filter_, string(), offset_, limit_, -1, random_id_, false, get_tries() < 3, std::move(promise)); } void do_send_result() override { From 0e668726bc93451bcfa9bee84955f258b6bc2517 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 18:09:32 +0300 Subject: [PATCH 03/29] Update can_unmute_self only if the user is muted. --- td/telegram/GroupCallManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 03c5cbf18..c9e178228 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1149,7 +1149,8 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou if (participant.user_id == td_->contacts_manager_->get_my_id()) { auto *group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); - if (group_call->is_joined && group_call->is_active && group_call->can_self_unmute != participant.can_self_unmute) { + if (group_call->is_joined && group_call->is_active && participant.is_muted && + group_call->can_self_unmute != participant.can_self_unmute) { group_call->can_self_unmute = participant.can_self_unmute; send_update_group_call(group_call, "process_group_call_participant"); } From ca242e754b28fa586ebdc9a8dfd39187e89314e0 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 18:40:51 +0300 Subject: [PATCH 04/29] Keep biggest update list for a given version instead of forced sync. --- td/telegram/GroupCallManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index c9e178228..4cd0ebc12 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -905,10 +905,9 @@ void GroupCallManager::on_update_group_call_participants( group_call_participants = make_unique(); } auto &pending_updates = group_call_participants->pending_updates_[version]; - if (!pending_updates.empty()) { + if (participants.size() <= pending_updates.size()) { LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in " << input_group_call_id; - sync_group_call_participants(input_group_call_id); return; } pending_updates = std::move(participants); From 0d7c980f9dff1340383d7cba1ed9b01c4b5ed0a7 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 18:57:21 +0300 Subject: [PATCH 05/29] Fix nullptr dereference during logging. --- td/telegram/GroupCallManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 4cd0ebc12..40d1126e4 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -735,6 +735,7 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i } auto group_call = get_group_call(input_group_call_id); + 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))); @@ -771,6 +772,7 @@ void GroupCallManager::on_get_group_call_participants( bool is_sync = is_load && offset.empty(); if (is_sync) { auto group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); is_sync = group_call->syncing_participants; if (is_sync) { group_call->syncing_participants = false; @@ -887,7 +889,7 @@ void GroupCallManager::on_update_group_call_participants( send_update_group_call(group_call, "on_update_group_call_participants"); } - LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id << " from " << group_call->dialog_id; + LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id; return; } if (version <= 0) { @@ -1859,8 +1861,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, if (!td_->contacts_manager_->have_user_force(user_id)) { if (recursive) { - LOG(ERROR) << "Failed to find speaking " << user_id << " from " << input_group_call_id << " in " - << group_call->dialog_id; + LOG(ERROR) << "Failed to find speaking " << user_id << " from " << input_group_call_id; } else { auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, user_id, date](Result &&result) { @@ -1874,8 +1875,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, return; } - LOG(INFO) << "Add " << user_id << " as recent speaker at " << date << " in " << input_group_call_id << " from " - << group_call->dialog_id; + LOG(INFO) << "Add " << user_id << " as recent speaker at " << date << " in " << input_group_call_id; auto &recent_speakers = group_call_recent_speakers_[group_call_id]; if (recent_speakers == nullptr) { recent_speakers = make_unique(); @@ -1919,7 +1919,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, void GroupCallManager::remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id) { auto *group_call = get_group_call(input_group_call_id); - if (group_call != nullptr && group_call->is_inited && !group_call->is_active) { + if (group_call == nullptr) { return; } From 6ebe28cdacb08ae2503740b15d729f1f4c111241 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 20:30:52 +0300 Subject: [PATCH 06/29] Load group call administrators. --- td/telegram/GroupCallManager.cpp | 113 +++++++++++++++++++++++++++---- td/telegram/GroupCallManager.h | 7 ++ 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 40d1126e4..c977b7c4d 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -8,6 +8,7 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/DialogParticipant.h" #include "td/telegram/Global.h" #include "td/telegram/MessagesManager.h" #include "td/telegram/misc.h" @@ -18,6 +19,7 @@ #include "td/utils/JsonBuilder.h" #include "td/utils/Random.h" +#include #include namespace td { @@ -422,6 +424,7 @@ struct GroupCallManager::GroupCallParticipants { string next_offset; int64 min_order = std::numeric_limits::max(); + vector administrator_user_ids; std::map>> pending_updates_; }; @@ -687,6 +690,12 @@ void GroupCallManager::get_group_call(GroupCallId group_call_id, void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id, Promise> &&promise) { + if (!promise && need_group_call_participants(input_group_call_id)) { + auto group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); + } + auto &queries = load_group_call_queries_[input_group_call_id]; queries.push_back(std::move(promise)); if (queries.size() == 1) { @@ -847,6 +856,17 @@ void GroupCallManager::on_get_group_call_participants( } } +GroupCallManager::GroupCallParticipants *GroupCallManager::add_group_call_participants( + InputGroupCallId input_group_call_id) { + CHECK(need_group_call_participants(input_group_call_id)); + + auto &participants = group_call_participants_[input_group_call_id]; + if (participants == nullptr) { + participants = make_unique(); + } + return participants.get(); +} + void GroupCallManager::on_update_group_call_participants( InputGroupCallId input_group_call_id, vector> &&participants, int32 version) { @@ -902,10 +922,7 @@ void GroupCallManager::on_update_group_call_participants( return; } - auto &group_call_participants = group_call_participants_[input_group_call_id]; - if (group_call_participants == nullptr) { - group_call_participants = make_unique(); - } + auto *group_call_participants = add_group_call_participants(input_group_call_id); auto &pending_updates = group_call_participants->pending_updates_[version]; if (participants.size() <= pending_updates.size()) { LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in " @@ -1157,11 +1174,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou } } - auto &participants = group_call_participants_[input_group_call_id]; - if (participants == nullptr) { - participants = make_unique(); - } - + auto *participants = add_group_call_participants(input_group_call_id); for (size_t i = 0; i < participants->participants.size(); i++) { auto &old_participant = participants->participants[i]; if (old_participant.user_id == participant.user_id) { @@ -1309,6 +1322,82 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id, }); request->query_ref = td_->create_handler(std::move(query_promise)) ->send(input_group_call_id, json_payload, is_muted, generation); + + try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); +} + +void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id) { + if (!dialog_id.is_valid() || !need_group_call_participants(input_group_call_id) || + can_manage_group_calls(dialog_id).is_error()) { + return; + } + + unique_ptr random_id_ptr = td::make_unique(); + auto random_id_raw = random_id_ptr.get(); + auto promise = PromiseCreator::lambda( + [actor_id = actor_id(this), input_group_call_id, random_id = std::move(random_id_ptr)](Result &&result) { + send_closure(actor_id, &GroupCallManager::finish_load_group_call_administrators, input_group_call_id, + *random_id, std::move(result)); + }); + td_->messages_manager_->search_dialog_participants( + dialog_id, string(), 100, DialogParticipantsFilter(DialogParticipantsFilter::Type::Administrators), + *random_id_raw, true, true, std::move(promise)); +} + +void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId input_group_call_id, int64 random_id, + Result &&result) { + if (G()->close_flag()) { + return; + } + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr); + if (!group_call->dialog_id.is_valid() || !can_manage_group_calls(group_call->dialog_id).is_ok()) { + return; + } + + vector administrator_user_ids; + if (result.is_ok()) { + result = Status::Error(500, "Failed to receive result"); + unique_ptr ignore_result = make_unique(); + auto ignore_result_ptr = ignore_result.get(); + auto promise = PromiseCreator::lambda([&result, ignore_result = std::move(ignore_result)](Result new_result) { + if (!*ignore_result) { + result = std::move(new_result); + } + }); + auto participants = td_->messages_manager_->search_dialog_participants( + group_call->dialog_id, string(), 100, DialogParticipantsFilter(DialogParticipantsFilter::Type::Administrators), + random_id, true, true, std::move(promise)); + for (auto &administrator : participants.second) { + if (administrator.status.can_manage_calls()) { + administrator_user_ids.push_back(administrator.user_id); + } + } + + *ignore_result_ptr = true; + } + + if (result.is_error()) { + LOG(WARNING) << "Failed to get administrators of " << input_group_call_id << ": " << result.error(); + return; + } + + if (!need_group_call_participants(input_group_call_id)) { + return; + } + + LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids; + auto *group_call_participants = add_group_call_participants(input_group_call_id); + std::unordered_set removed_user_ids(group_call_participants->administrator_user_ids.begin(), + group_call_participants->administrator_user_ids.end()); + std::unordered_set added_user_ids; + for (auto user_id : administrator_user_ids) { + if (removed_user_ids.erase(user_id) == 0) { + added_user_ids.insert(user_id); + } + } + group_call_participants->administrator_user_ids = std::move(administrator_user_ids); } void GroupCallManager::process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation, @@ -1744,6 +1833,7 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptrdialog_id); } else { group_call->version = -1; } @@ -1821,10 +1911,7 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou } // found a gap - auto &group_call_participants = group_call_participants_[input_group_call_id]; - if (group_call_participants == nullptr) { - group_call_participants = make_unique(); - } + auto *group_call_participants = add_group_call_participants(input_group_call_id); group_call_participants->pending_updates_[version]; // reserve place for updates sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0); } diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index bf769b4e5..7d99da3bc 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -133,10 +133,17 @@ class GroupCallManager : public Actor { int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant); + void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id); + + void finish_load_group_call_administrators(InputGroupCallId input_group_call_id, int64 random_id, + Result &&result); + bool on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response); void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error); + GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id); + void on_group_call_left(InputGroupCallId input_group_call_id, int32 source); void on_group_call_left_impl(GroupCall *group_call); From 4a3375e61780b0bb4b9b03c170d0bb87ca245ee7 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 16 Dec 2020 22:49:24 +0300 Subject: [PATCH 07/29] Various group call fixes. --- td/telegram/GroupCallManager.cpp | 12 +++++++----- td/telegram/GroupCallParticipant.cpp | 7 +++---- td/telegram/cli.cpp | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index c977b7c4d..e51835da0 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -959,10 +959,10 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup if (version <= group_call->version) { for (auto &group_call_participant : participants) { GroupCallParticipant participant(group_call_participant); + on_participant_speaking_in_group_call(input_group_call_id, participant); if (participant.user_id == td_->contacts_manager_->get_my_id()) { process_group_call_participant(input_group_call_id, std::move(participant)); } - on_participant_speaking_in_group_call(input_group_call_id, participant); } LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in " << input_group_call_id << " from " << group_call->dialog_id; @@ -1167,8 +1167,8 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou if (participant.user_id == td_->contacts_manager_->get_my_id()) { auto *group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); - if (group_call->is_joined && group_call->is_active && participant.is_muted && - group_call->can_self_unmute != participant.can_self_unmute) { + if (group_call->is_joined && group_call->is_active && participant.source == group_call->source && + participant.is_muted && group_call->can_self_unmute != participant.can_self_unmute) { group_call->can_self_unmute = participant.can_self_unmute; send_update_group_call(group_call, "process_group_call_participant"); } @@ -1206,12 +1206,14 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou participant.is_just_joined = false; if (old_participant != participant) { - bool need_update = old_participant.order != 0 || participant.order != 0; + LOG(INFO) << "Update " << old_participant << " to " << participant; + bool need_update = + old_participant.order != 0 || participant.order != 0 || old_participant.source != participant.source; old_participant = std::move(participant); if (need_update) { send_update_group_call_participant(input_group_call_id, old_participant); } - on_participant_speaking_in_group_call(input_group_call_id, participant); + on_participant_speaking_in_group_call(input_group_call_id, old_participant); } return 0; } diff --git a/td/telegram/GroupCallParticipant.cpp b/td/telegram/GroupCallParticipant.cpp index 841a4ea75..f37acef0d 100644 --- a/td/telegram/GroupCallParticipant.cpp +++ b/td/telegram/GroupCallParticipant.cpp @@ -43,10 +43,9 @@ td_api::object_ptr GroupCallParticipant::get_group bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) { return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.is_muted == rhs.is_muted && - lhs.can_self_unmute == rhs.can_self_unmute && - max(lhs.active_date, lhs.local_active_date) == max(rhs.active_date, rhs.local_active_date) && - lhs.joined_date == rhs.joined_date && lhs.is_speaking == rhs.is_speaking || - lhs.order != rhs.order; + lhs.can_self_unmute == rhs.can_self_unmute && lhs.joined_date == rhs.joined_date && + max(lhs.active_date, lhs.local_active_date) == max(rhs.active_date, rhs.local_active_date) && + lhs.is_speaking == rhs.is_speaking && lhs.order == rhs.order; } bool operator!=(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 0a0cc0f33..e1e5d8c5e 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2850,7 +2850,7 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_group_call_id(args), nullptr, 123, true)); } else if (op == "tgcmnp" || op == "tgcmnpe") { send_request( - td_api::make_object(as_group_call_id(args), op == "tgcmnme")); + td_api::make_object(as_group_call_id(args), op == "tgcmnpe")); } else if (op == "sgcpis") { string group_call_id; string source; From bfcc7d17c49bf31fa1deb72671b617e9c30df298 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 00:37:42 +0300 Subject: [PATCH 08/29] Improve GroupCallParticipant updating. --- td/telegram/GroupCallManager.cpp | 16 ++++++---------- td/telegram/GroupCallParticipant.cpp | 4 +--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index e51835da0..e629a6c74 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1188,7 +1188,6 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou return -1; } - LOG(INFO) << "Edit " << old_participant; if (participant.joined_date < old_participant.joined_date) { LOG(ERROR) << "Join date of " << participant.user_id << " in " << input_group_call_id << " decreased from " << old_participant.joined_date << " to " << participant.joined_date; @@ -1205,16 +1204,13 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou } participant.is_just_joined = false; - if (old_participant != participant) { - LOG(INFO) << "Update " << old_participant << " to " << participant; - bool need_update = - old_participant.order != 0 || participant.order != 0 || old_participant.source != participant.source; - old_participant = std::move(participant); - if (need_update) { - send_update_group_call_participant(input_group_call_id, old_participant); - } - on_participant_speaking_in_group_call(input_group_call_id, old_participant); + LOG(INFO) << "Edit " << old_participant << " to " << participant; + if (old_participant != participant && + (old_participant.order != 0 || participant.order != 0 || old_participant.source != participant.source)) { + send_update_group_call_participant(input_group_call_id, participant); } + on_participant_speaking_in_group_call(input_group_call_id, participant); + old_participant = std::move(participant); return 0; } } diff --git a/td/telegram/GroupCallParticipant.cpp b/td/telegram/GroupCallParticipant.cpp index f37acef0d..c28ca0727 100644 --- a/td/telegram/GroupCallParticipant.cpp +++ b/td/telegram/GroupCallParticipant.cpp @@ -43,9 +43,7 @@ td_api::object_ptr GroupCallParticipant::get_group bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) { return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.is_muted == rhs.is_muted && - lhs.can_self_unmute == rhs.can_self_unmute && lhs.joined_date == rhs.joined_date && - max(lhs.active_date, lhs.local_active_date) == max(rhs.active_date, rhs.local_active_date) && - lhs.is_speaking == rhs.is_speaking && lhs.order == rhs.order; + lhs.can_self_unmute == rhs.can_self_unmute && lhs.is_speaking == rhs.is_speaking && lhs.order == rhs.order; } bool operator!=(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) { From c4d8f301a1ba51797f924e7f78373beff935fa8c Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 02:07:05 +0300 Subject: [PATCH 09/29] Add groupCallParticipant.can_be_muted/can_be_unmuted flags. --- td/generate/scheme/td_api.tl | 14 +++++-- td/generate/scheme/td_api.tlo | Bin 191364 -> 191444 bytes td/telegram/GroupCallManager.cpp | 54 ++++++++++++++++++++++----- td/telegram/GroupCallManager.h | 10 ++++- td/telegram/GroupCallParticipant.cpp | 33 ++++++++++++++-- td/telegram/GroupCallParticipant.h | 13 +++++-- 6 files changed, 102 insertions(+), 22 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 9a34f2a5f..2af5ad631 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2093,10 +2093,16 @@ groupCallJoinResponseCandidate port:string protocol:string network:string genera //@description Describes a join response for interaction with tgcalls @payload Join response payload to pass to tgcalls @candidates Join response candidates to pass to tgcalls groupCallJoinResponse payload:groupCallPayload candidates:vector = GroupCallJoinResponse; -//@description Represents a group call participant @user_id Identifier of the user @source User's synchronization source -//@is_speaking True, if the user is speaking as set by setGroupCallParticipantIsSpeaking @is_muted True, if the user is muted @can_unmute_self True, if the user can unmute themself +//@description Represents a group call participant +//@user_id Identifier of the user +//@source User's synchronization source +//@is_speaking True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking +//@can_be_muted True, if current user can mute the participant +//@can_be_unmuted True, if the current user can allow the participant to unmute themself or unmute the participant (only for self) +//@is_muted True, if the participant is muted +//@can_unmute_self True, if the participant can unmute themself //@order User's order in the group call participant list. The bigger is order, the higher is user in the list. If order is 0, the user must be removed from the participant list -groupCallParticipant user_id:int32 source:int32 is_speaking:Bool is_muted:Bool can_unmute_self:Bool order:int64 = GroupCallParticipant; +groupCallParticipant user_id:int32 source:int32 is_speaking:Bool can_be_muted:Bool can_be_unmuted:Bool is_muted:Bool can_unmute_self:Bool order:int64 = GroupCallParticipant; //@class CallProblem @description Describes the exact type of a problem with a call @@ -4381,7 +4387,7 @@ inviteGroupCallParticipants group_call_id:int32 user_ids:vector = Ok; //@source Group call participant's synchronization source identifier @is_speaking True, if the user is speaking setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:Bool = Ok; -//@description Toggles whether a group call participant is muted. Requires can_manage_voice_chats rights to mute other group call participants +//@description Toggles whether a group call participant is muted, unmuted, or allowed to unmute themself //@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; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index cf6a5c248cc452ae2e512857f5591ea2bc0d6a83..9c8b041e9c91aab19e8a0aa81872d93fc331da8f 100644 GIT binary patch delta 115 zcmZp<&VA)N_l6rnEM6U4lEOvs00^2HR5$+>%-d3ll( z^Wu|I<8w<(Qd1^B^pc)#Bgn|XQks`rIyoUoX7Yx;1z@9^RrYOH*~i#m&I&SvaeCu5 NM)~b0zB2Cl3II5FF>L?< delta 82 zcmca|ox9~a_l6rnEbrbjJ=uIm$Ym89h$WIf`JRv%Cy06Tn2-dialog_id).is_ok(); +} + void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise &&promise) { if (!dialog_id.is_valid()) { return promise.set_error(Status::Error(400, "Invalid chat identifier specified")); @@ -694,6 +702,13 @@ void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id, auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); + + auto participants_it = group_call_participants_.find(input_group_call_id); + if (participants_it != group_call_participants_.end()) { + CHECK(participants_it->second != nullptr); + update_group_call_participants_can_be_muted( + input_group_call_id, can_manage_group_calls(group_call->dialog_id).is_ok(), participants_it->second.get()); + } } auto &queries = load_group_call_queries_[input_group_call_id]; @@ -1152,6 +1167,25 @@ void GroupCallManager::process_group_call_participants( } } +bool GroupCallManager::update_group_call_participant_can_be_muted(bool can_manage, + const GroupCallParticipants *participants, + GroupCallParticipant &participant) { + bool is_self = participant.user_id == td_->contacts_manager_->get_my_id(); + bool is_admin = td::contains(participants->administrator_user_ids, participant.user_id); + return participant.update_can_be_muted(can_manage, is_self, is_admin); +} + +void GroupCallManager::update_group_call_participants_can_be_muted(InputGroupCallId input_group_call_id, + bool can_manage, + GroupCallParticipants *participants) { + CHECK(participants != nullptr); + for (auto &participant : participants->participants) { + if (update_group_call_participant_can_be_muted(can_manage, participants, participant) && participant.order != 0) { + send_update_group_call_participant(input_group_call_id, participant); + } + } +} + int GroupCallManager::process_group_call_participant(InputGroupCallId input_group_call_id, GroupCallParticipant &&participant) { if (!participant.is_valid()) { @@ -1174,6 +1208,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou } } + bool can_manage = can_manage_group_call(input_group_call_id); auto *participants = add_group_call_participants(input_group_call_id); for (size_t i = 0; i < participants->participants.size(); i++) { auto &old_participant = participants->participants[i]; @@ -1203,6 +1238,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou participant.order = real_order; } participant.is_just_joined = false; + update_group_call_participant_can_be_muted(can_manage, participants, participant); LOG(INFO) << "Edit " << old_participant << " to " << participant; if (old_participant != participant && @@ -1368,7 +1404,7 @@ void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId in group_call->dialog_id, string(), 100, DialogParticipantsFilter(DialogParticipantsFilter::Type::Administrators), random_id, true, true, std::move(promise)); for (auto &administrator : participants.second) { - if (administrator.status.can_manage_calls()) { + if (administrator.status.can_manage_calls() && administrator.user_id != td_->contacts_manager_->get_my_id()) { administrator_user_ids.push_back(administrator.user_id); } } @@ -1385,17 +1421,15 @@ void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId in return; } - LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids; auto *group_call_participants = add_group_call_participants(input_group_call_id); - std::unordered_set removed_user_ids(group_call_participants->administrator_user_ids.begin(), - group_call_participants->administrator_user_ids.end()); - std::unordered_set added_user_ids; - for (auto user_id : administrator_user_ids) { - if (removed_user_ids.erase(user_id) == 0) { - added_user_ids.insert(user_id); - } + if (group_call_participants->administrator_user_ids == administrator_user_ids) { + return; } + + LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids; group_call_participants->administrator_user_ids = std::move(administrator_user_ids); + + update_group_call_participants_can_be_muted(input_group_call_id, true, group_call_participants); } void GroupCallManager::process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation, diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index 7d99da3bc..db7a2bc1b 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -112,7 +112,9 @@ class GroupCallManager : public Actor { const GroupCall *get_group_call(InputGroupCallId input_group_call_id) const; GroupCall *get_group_call(InputGroupCallId input_group_call_id); - Status can_manage_group_calls(DialogId dialog_id); + Status can_manage_group_calls(DialogId dialog_id) const; + + bool can_manage_group_call(InputGroupCallId input_group_call_id) const; void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise &&promise); @@ -131,6 +133,12 @@ class GroupCallManager : public Actor { vector> &&participants, bool is_load, bool is_sync); + bool update_group_call_participant_can_be_muted(bool can_manage, const GroupCallParticipants *participants, + GroupCallParticipant &participant); + + void update_group_call_participants_can_be_muted(InputGroupCallId input_group_call_id, bool can_manage, + GroupCallParticipants *participants); + int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant); void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id); diff --git a/td/telegram/GroupCallParticipant.cpp b/td/telegram/GroupCallParticipant.cpp index c28ca0727..39f11f2b2 100644 --- a/td/telegram/GroupCallParticipant.cpp +++ b/td/telegram/GroupCallParticipant.cpp @@ -30,6 +30,32 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptrjust_joined_; } +bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) { + bool new_can_be_muted = false; + bool new_can_be_unmuted = false; + if (is_self) { + // current user can be muted if !is_muted; after that is_muted && can_self_unmute + // current user can be unmuted if is_muted && can_self_unmute; after that !is_muted + new_can_be_muted = !is_muted; + new_can_be_unmuted = is_muted && can_self_unmute; + } else if (is_admin) { + // admin user can be muted if can_manage && !is_muted; after that is_muted && can_self_unmute + // admin user can't be unmuted + new_can_be_muted = can_manage && !is_muted; + } else { + // other user can be muted if can_manage; after that is_muted && !can_self_unmute + // other user can be unmuted if can_manage && is_muted && !can_self_unmute; after that is_muted && can_self_unmute + new_can_be_muted = can_manage && (!is_muted || can_self_unmute); + new_can_be_unmuted = can_manage && is_muted && !can_self_unmute; + } + if (new_can_be_muted != can_be_muted || new_can_be_unmuted != can_be_unmuted) { + can_be_muted = new_can_be_muted; + can_be_unmuted = new_can_be_unmuted; + return true; + } + return false; +} + td_api::object_ptr GroupCallParticipant::get_group_call_participant_object( ContactsManager *contacts_manager) const { if (!is_valid()) { @@ -37,12 +63,13 @@ td_api::object_ptr GroupCallParticipant::get_group } return td_api::make_object( - contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), source, is_speaking, is_muted, - can_self_unmute, order); + contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), source, is_speaking, + can_be_muted, can_be_unmuted, is_muted, can_self_unmute, order); } bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) { - return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.is_muted == rhs.is_muted && + return lhs.user_id == rhs.user_id && lhs.source == rhs.source && lhs.can_be_muted == rhs.can_be_muted && + lhs.can_be_unmuted == rhs.can_be_unmuted && lhs.is_muted == rhs.is_muted && lhs.can_self_unmute == rhs.can_self_unmute && lhs.is_speaking == rhs.is_speaking && lhs.order == rhs.order; } diff --git a/td/telegram/GroupCallParticipant.h b/td/telegram/GroupCallParticipant.h index 398ac2720..c78531e2f 100644 --- a/td/telegram/GroupCallParticipant.h +++ b/td/telegram/GroupCallParticipant.h @@ -25,11 +25,20 @@ struct GroupCallParticipant { int32 joined_date = 0; int32 active_date = 0; + bool can_be_muted = false; + bool can_be_unmuted = false; + bool is_just_joined = false; bool is_speaking = false; int32 local_active_date = 0; int64 order = 0; + GroupCallParticipant() = default; + + explicit GroupCallParticipant(const tl_object_ptr &participant); + + bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin); + int64 get_real_order() const { return (static_cast(max(active_date, local_active_date)) << 32) + joined_date; } @@ -38,10 +47,6 @@ struct GroupCallParticipant { return user_id.is_valid(); } - GroupCallParticipant() = default; - - explicit GroupCallParticipant(const tl_object_ptr &participant); - td_api::object_ptr get_group_call_participant_object( ContactsManager *contacts_manager) const; }; From e89d353b68d1097605f58894fd46931052ec3cf9 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 17:24:07 +0300 Subject: [PATCH 10/29] Add groupCall.need_rejoin flag. --- td/generate/scheme/td_api.tl | 6 ++-- td/generate/scheme/td_api.tlo | Bin 191444 -> 191480 bytes td/telegram/GroupCallManager.cpp | 53 +++++++++++++++++++++++-------- td/telegram/GroupCallManager.h | 4 +-- td/telegram/UpdatesManager.cpp | 4 +-- 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2af5ad631..db01646d1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2070,6 +2070,7 @@ callStateError error:error = CallState; //@id Group call identifier //@is_active True, if the call is active //@is_joined True, if the call is joined +//@need_rejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined //@can_unmute_self True, if the user can unmute themself //@participant_count Number of participants in the group call //@loaded_all_participants True, if all group call participants are loaded @@ -2077,7 +2078,7 @@ callStateError error:error = CallState; //@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 can_unmute_self: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 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; //@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; @@ -3415,8 +3416,7 @@ updateCall call:call = Update; updateGroupCall group_call:groupCall = Update; //@description Information about a group call participant was changed. The updates are sent only after the group call is received through getGroupCall and only if the call is joined or being joined -//@group_call_id Identifier of group call -//@participant New data about a participant. If this is a current user with different source, then the current user joined the call from another device and the call must not be rejoined automatically +//@group_call_id Identifier of group call @participant New data about a participant updateGroupCallParticipant group_call_id:int32 participant:groupCallParticipant = Update; //@description New call signaling data arrived @call_id The call identifier @data The data diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 9c8b041e9c91aab19e8a0aa81872d93fc331da8f..27d92657ef5833e24ac95a56accc365d79bd92a5 100644 GIT binary patch delta 122 zcmca|o%_di?hO(`EZ$0m9Ghi?G?qz%Se)ra`K1NUi8(n83?Tl^V?sXMlMB6+CpYZy z;Ni|oO-+d}O3lj8%-g(SM+GBTceBo}?K-;{Ev#8VIvA%XzGqa}-uadBd>L4J@`eHn MFk}0S944E304*dcUH||9 delta 110 zcmexyo%_ml?hO(`EK=njC7Wf0G?s~gSe)ra`K1NUi8(n83?Tkwg&Pu+3wA_Iie{bc zyH9zu$W9AJu$Jb4UE2e8Fcontacts_manager_->get_my_id() && group_call != nullptr && group_call->is_inited && group_call->is_joined && (participant.joined_date == 0) == (participant.source == group_call->source)) { - on_group_call_left_impl(group_call); + on_group_call_left_impl(group_call, participant.joined_date == 0); need_update = true; } if (participant.joined_date == 0) { @@ -967,6 +969,7 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup int32 diff = 0; bool is_left = false; + bool need_rejoin = true; while (!pending_updates.empty()) { auto it = pending_updates.begin(); auto version = it->first; @@ -998,6 +1001,9 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup if (group_call_participant.user_id == td_->contacts_manager_->get_my_id() && group_call->is_joined && (group_call_participant.joined_date == 0) == (group_call_participant.source == group_call->source)) { is_left = true; + if (group_call_participant.joined_date != 0) { + need_rejoin = false; + } } diff += process_group_call_participant(input_group_call_id, std::move(group_call_participant)); } @@ -1025,7 +1031,7 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup update_group_call_dialog(group_call, "process_pending_group_call_participant_updates"); } if (is_left && group_call->is_joined) { - on_group_call_left_impl(group_call); + on_group_call_left_impl(group_call, need_rejoin); need_update = true; } if (need_update) { @@ -1241,8 +1247,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou update_group_call_participant_can_be_muted(can_manage, participants, participant); LOG(INFO) << "Edit " << old_participant << " to " << participant; - if (old_participant != participant && - (old_participant.order != 0 || participant.order != 0 || old_participant.source != participant.source)) { + if (old_participant != participant && (old_participant.order != 0 || participant.order != 0)) { send_update_group_call_participant(input_group_call_id, participant); } on_participant_speaking_in_group_call(input_group_call_id, participant); @@ -1291,6 +1296,11 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id, if (group_call->is_inited && !group_call->is_active) { return promise.set_error(Status::Error(400, "Group call is finished")); } + if (group_call->need_rejoin) { + group_call->need_rejoin = false; + send_update_group_call(group_call, "join_group_call"); + } + group_call->is_being_left = false; if (pending_join_requests_.count(input_group_call_id)) { auto it = pending_join_requests_.find(input_group_call_id); @@ -1527,6 +1537,8 @@ bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_ auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr); group_call->is_joined = true; + group_call->need_rejoin = false; + group_call->is_being_left = false; group_call->joined_date = G()->unix_time(); group_call->source = it->second->source; it->second->promise.set_value(result.move_as_ok()); @@ -1673,7 +1685,7 @@ void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Pro 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() - 10) { + 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; @@ -1681,7 +1693,7 @@ void GroupCallManager::check_group_call_is_joined(GroupCallId group_call_id, Pro 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); + send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, true); result = Unit(); } promise.set_result(std::move(result)); @@ -1723,30 +1735,33 @@ void GroupCallManager::leave_group_call(GroupCallId group_call_id, Promise return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING")); } auto source = group_call->source; + group_call->is_being_left = true; 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_ok()) { // just in case - send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source); + send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source, false); } promise.set_result(std::move(result)); }); td_->create_handler(std::move(query_promise))->send(input_group_call_id, source); } -void GroupCallManager::on_group_call_left(InputGroupCallId input_group_call_id, int32 source) { +void GroupCallManager::on_group_call_left(InputGroupCallId input_group_call_id, int32 source, bool need_rejoin) { auto *group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); if (group_call->is_joined && group_call->source == source) { - on_group_call_left_impl(group_call); + on_group_call_left_impl(group_call, need_rejoin); send_update_group_call(group_call, "on_group_call_left"); } } -void GroupCallManager::on_group_call_left_impl(GroupCall *group_call) { +void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_rejoin) { CHECK(group_call != nullptr && group_call->is_inited && group_call->is_joined); group_call->is_joined = false; + group_call->need_rejoin = need_rejoin && !group_call->is_being_left; + group_call->is_being_left = false; group_call->is_speaking = false; group_call->can_self_unmute = false; group_call->joined_date = 0; @@ -1766,7 +1781,7 @@ void GroupCallManager::on_update_group_call(tl_object_ptrparticipant_count << " participants and version " << group_call->version; if (!group_call->is_inited) { + call.is_joined = group_call->is_joined; + call.need_rejoin = group_call->need_rejoin; + call.is_being_left = group_call->is_being_left; + call.is_speaking = group_call->is_speaking; + call.can_self_unmute = group_call->can_self_unmute; + call.syncing_participants = group_call->syncing_participants; + call.loaded_all_participants = group_call->loaded_all_participants; + call.source = group_call->source; *group_call = std::move(call); + if (need_group_call_participants(input_group_call_id)) { // init version group_call->version = call.version; @@ -2161,9 +2185,10 @@ tl_object_ptr GroupCallManager::get_group_call_object(const G 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->can_self_unmute, - group_call->participant_count, group_call->loaded_all_participants, std::move(recent_speaker_user_ids), - group_call->mute_new_participants, group_call->allowed_change_mute_new_participants, group_call->duration); + 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->participant_count, group_call->loaded_all_participants, + std::move(recent_speaker_user_ids), group_call->mute_new_participants, + group_call->allowed_change_mute_new_participants, group_call->duration); } tl_object_ptr GroupCallManager::get_update_group_call_object( diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index db7a2bc1b..1f130df7f 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -152,9 +152,9 @@ class GroupCallManager : public Actor { GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id); - void on_group_call_left(InputGroupCallId input_group_call_id, int32 source); + void on_group_call_left(InputGroupCallId input_group_call_id, int32 source, bool need_rejoin); - void on_group_call_left_impl(GroupCall *group_call); + void on_group_call_left_impl(GroupCall *group_call, bool need_rejoin); InputGroupCallId update_group_call(const tl_object_ptr &group_call_ptr, DialogId dialog_id); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index c44cddab4..c8e3ac4ae 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -2153,9 +2153,9 @@ void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { DialogId dialog_id(ChatId(update->chat_id_)); - if (!td_->messages_manager_->have_dialog(dialog_id)) { + if (!td_->messages_manager_->have_dialog_force(dialog_id)) { dialog_id = DialogId(ChannelId(update->chat_id_)); - if (!td_->messages_manager_->have_dialog(dialog_id)) { + if (!td_->messages_manager_->have_dialog_force(dialog_id)) { dialog_id = DialogId(); } } From 7a6c393b7b2f2cf75ffb038fa72d7c9d08a3fc6b Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 18:20:28 +0300 Subject: [PATCH 11/29] Update MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN limit. --- td/telegram/MessagesManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 2c5e88851..f0b7742e8 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1675,7 +1675,7 @@ class MessagesManager : public Actor { static constexpr int32 MAX_GET_DIALOGS = 100; // server side limit static constexpr int32 MAX_GET_HISTORY = 100; // server side limit static constexpr int32 MAX_SEARCH_MESSAGES = 100; // server side limit - static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 5; // server side limit + static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 4; // server side limit static constexpr int32 MIN_CHANNEL_DIFFERENCE = 10; static constexpr int32 MAX_CHANNEL_DIFFERENCE = 100; static constexpr int32 MAX_BOT_CHANNEL_DIFFERENCE = 100000; // server side limit From 2a5068532193e7ce0ed2c6c34265d4a965b4c5dc Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 18:27:01 +0300 Subject: [PATCH 12/29] Add separate GroupCallManager::on_update_group_call_rights method. --- td/telegram/GroupCallManager.cpp | 10 +++++++--- td/telegram/GroupCallManager.h | 2 ++ td/telegram/MessagesManager.cpp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 6cb69062b..557f056a3 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -698,9 +698,8 @@ void GroupCallManager::get_group_call(GroupCallId group_call_id, reload_group_call(input_group_call_id, std::move(promise)); } -void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id, - Promise> &&promise) { - if (!promise && need_group_call_participants(input_group_call_id)) { +void GroupCallManager::on_update_group_call_rights(InputGroupCallId input_group_call_id) { + if (need_group_call_participants(input_group_call_id)) { auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); @@ -713,6 +712,11 @@ void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id, } } + reload_group_call(input_group_call_id, Auto()); +} + +void GroupCallManager::reload_group_call(InputGroupCallId input_group_call_id, + Promise> &&promise) { auto &queries = load_group_call_queries_[input_group_call_id]; queries.push_back(std::move(promise)); if (queries.size() == 1) { diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index 1f130df7f..8fec9b725 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -41,6 +41,8 @@ class GroupCallManager : public Actor { void get_group_call(GroupCallId group_call_id, Promise> &&promise); + void on_update_group_call_rights(InputGroupCallId input_group_call_id); + void reload_group_call(InputGroupCallId input_group_call_id, Promise> &&promise); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 01a47336d..63916e743 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -10663,7 +10663,7 @@ void MessagesManager::reload_dialog_group_call(DialogId dialog_id) { } if (d->active_group_call_id.is_valid()) { - td_->group_call_manager_->reload_group_call(d->active_group_call_id, Auto()); + td_->group_call_manager_->on_update_group_call_rights(d->active_group_call_id); } } From e856788f5229cba9a7f8e083ddaa8f561b2f5762 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 18:38:27 +0300 Subject: [PATCH 13/29] Reload group call when chat is opened. --- td/telegram/MessagesManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 63916e743..c85e23b76 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -19122,6 +19122,10 @@ void MessagesManager::open_dialog(Dialog *d) { get_dialog_pinned_message(dialog_id, Auto()); + if (d->active_group_call_id.is_valid()) { + td_->group_call_manager_->reload_group_call(d->active_group_call_id, Auto()); + } + switch (dialog_id.get_type()) { case DialogType::User: break; From 89b6d7faa098a744c281086e4f67f2bfce9e6da3 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 22:55:29 +0300 Subject: [PATCH 14/29] tg_cli: use custom call source. --- td/telegram/cli.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e1e5d8c5e..95b046302 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2845,9 +2845,9 @@ class CliClient final : public Actor { fingerprints.push_back(td_api::make_object("h2", "s2", "fingerprint2")); send_request(td_api::make_object( as_group_call_id(args), - td_api::make_object("ufrag", "pwd", std::move(fingerprints)), 123, true)); + td_api::make_object("ufrag", "pwd", std::move(fingerprints)), group_call_source_, true)); } else if (op == "jgcc") { - send_request(td_api::make_object(as_group_call_id(args), nullptr, 123, true)); + send_request(td_api::make_object(as_group_call_id(args), nullptr, 0, true)); } else if (op == "tgcmnp" || op == "tgcmnpe") { send_request( td_api::make_object(as_group_call_id(args), op == "tgcmnpe")); @@ -4548,6 +4548,8 @@ class CliClient final : public Actor { int api_id_ = 0; std::string api_hash_; + int32 group_call_source_ = Random::fast(1, 1000000000); + static std::atomic cpu_counter_; }; CliClient *CliClient::instance_ = nullptr; From f5a122c65d1a632d35631bf43a3fc37b466b067a Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 23:12:06 +0300 Subject: [PATCH 15/29] Allow zero source in setGroupCallParticipantIsSpeaking. --- td/telegram/GroupCallManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 557f056a3..340d33a14 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1611,6 +1611,9 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_ if (group_call == nullptr || !group_call->is_inited || !group_call->is_active || !group_call->is_joined) { return promise.set_value(Unit()); } + if (source == 0) { + source = group_call->source; + } bool recursive = false; if (date == 0) { From 7aadb29e0a609d40ed09d33ac2528594dcf61941 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 23:14:37 +0300 Subject: [PATCH 16/29] Improve documentation. --- td/generate/scheme/td_api.tl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index db01646d1..9f7708d1c 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -953,7 +953,7 @@ keyboardButton text:string type:KeyboardButtonType = KeyboardButton; //@description A button that opens a specified URL @url HTTP or tg:// URL to open inlineKeyboardButtonTypeUrl url:string = InlineKeyboardButtonType; -//@description A button that opens a specified URL and automatically logs in in current user if they allowed to do that @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages +//@description A button that opens a specified URL and automatically authorize the current user if allowed to do so @url An HTTP URL to open @id Unique button identifier @forward_text If non-empty, new text of the button in forwarded messages inlineKeyboardButtonTypeLoginUrl url:string id:int32 forward_text:string = InlineKeyboardButtonType; //@description A button that sends a callback query to a bot @data Data to be sent to the bot via a callback query @@ -1989,7 +1989,7 @@ stickerSet id:int64 title:string name:string thumbnail:thumbnail thumbnail_outli //@description Represents short information about a sticker set //@id Identifier of the sticker set @title Title of the sticker set @name Name of the sticker set @thumbnail Sticker set thumbnail in WEBP or TGS format with width and height 100; may be null //@thumbnail_outline Sticker set thumbnail's outline represented as a list of closed vector paths; may be empty. The coordinate system origin is in the upper-left corner -//@is_installed True, if the sticker set has been installed by current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously +//@is_installed True, if the sticker set has been installed by the current user @is_archived True, if the sticker set has been archived. A sticker set can't be installed and archived simultaneously //@is_official True, if the sticker set is official @is_animated True, is the stickers in the set are animated @is_masks True, if the stickers in the set are masks @is_viewed True for already viewed trending sticker sets //@size Total number of stickers in the set @covers Contains up to the first 5 stickers from the set, depending on the context. If the application needs more stickers the full set should be requested stickerSetInfo id:int64 title:string name:string thumbnail:thumbnail thumbnail_outline:vector is_installed:Bool is_archived:Bool is_official:Bool is_animated:Bool is_masks:Bool is_viewed:Bool size:int32 covers:vector = StickerSetInfo; @@ -2098,7 +2098,7 @@ groupCallJoinResponse payload:groupCallPayload candidates:vector = Ok; //@description Informs TDLib that a group call participant speaking state has changed @group_call_id Group call identifier -//@source Group call participant's synchronization source identifier @is_speaking True, if the user is speaking +//@source Group call participant's synchronization source identifier, or 0 for the current user @is_speaking True, if the user is speaking setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:Bool = Ok; //@description Toggles whether a group call participant is muted, unmuted, or allowed to unmute themself @@ -4439,7 +4439,7 @@ removeContacts user_ids:vector = Ok; //@description Returns the total number of imported contacts getImportedContactCount = Count; -//@description Changes imported contacts using the list of current user contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts. +//@description Changes imported contacts using the list of contacts saved on the device. Imports newly added contacts and, if at least the file database is enabled, deletes recently deleted contacts. //-Query result depends on the result of the previous query, so only one query is possible at the same time @contacts The new list of contacts, contact's vCard are ignored and are not imported changeImportedContacts contacts:vector = ImportedContacts; @@ -4945,7 +4945,7 @@ setAlarm seconds:double = Ok; //@description Returns information about existing countries. Can be called before authorization getCountries = Countries; -//@description Uses current user IP address to find their country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization +//@description Uses the current IP address to find the current country. Returns two-letter ISO 3166-1 alpha-2 country code. Can be called before authorization getCountryCode = Text; //@description Returns information about a phone number by its prefix. Can be called before authorization @phone_number_prefix The phone number prefix From 8dd4fe31667e7c656850c1923d1d51d43fe206f0 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 18 Dec 2020 15:20:05 +0300 Subject: [PATCH 17/29] Separately apply versioned and unversioned group call updates. --- td/generate/scheme/telegram_api.tl | 2 +- td/generate/scheme/telegram_api.tlo | Bin 224296 -> 224340 bytes td/telegram/ContactsManager.cpp | 4 +- td/telegram/GroupCallManager.cpp | 76 +++++++++++++++++++-------- td/telegram/GroupCallParticipant.cpp | 4 ++ td/telegram/GroupCallParticipant.h | 6 ++- td/telegram/MessagesManager.cpp | 2 +- td/telegram/MessagesManager.h | 2 +- td/telegram/cli.cpp | 3 ++ 9 files changed, 70 insertions(+), 29 deletions(-) diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index bc3a06eca..247f4c884 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -1182,7 +1182,7 @@ groupCall#55903081 flags:# join_muted:flags.1?true can_change_join_muted:flags.2 inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall; -groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant; +groupCallParticipant#56b087c9 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true user_id:int date:int active_date:flags.3?int source:int = GroupCallParticipant; phone.groupCall#66ab0bfc call:GroupCall participants:Vector participants_next_offset:string users:Vector = phone.GroupCall; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index d8a062fd16f66399b586657cb76eebe78bada80a..fa0b7fc553bb329c9f639223409398e6b758196f 100644 GIT binary patch delta 54 zcmV-60LlNT*bUU!4X`w}mxMk6ER$fitO^NsWpZ_r-T(jq delta 52 zcmV-40L%Z>*bS)I4X`w}mt=1NEtjoR11OWdX%CZ3ofwm_wp^2NU?7v=U?78dw}*JQ K0k?R!0^GECEEq!o diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 872851ee6..220e50996 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -11722,7 +11722,7 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti } } if (need_reload_group_call) { - td_->messages_manager_->reload_dialog_group_call(DialogId(chat_id)); + td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(chat_id)); } c->is_changed = true; @@ -12064,7 +12064,7 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id reload_dialog_administrators(DialogId(channel_id), 0, Auto()); } if (need_reload_group_call) { - td_->messages_manager_->reload_dialog_group_call(DialogId(channel_id)); + td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(channel_id)); } } diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 340d33a14..a8f2083d1 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -427,7 +427,9 @@ struct GroupCallManager::GroupCallParticipants { int64 min_order = std::numeric_limits::max(); vector administrator_user_ids; - std::map>> pending_updates_; + + std::map>> pending_version_updates_; + std::map>> pending_mute_updates_; }; struct GroupCallManager::GroupCallRecentSpeakers { @@ -870,6 +872,9 @@ void GroupCallManager::on_get_group_call_participants( group_call->loaded_all_participants = false; need_update = true; } + if (process_pending_group_call_participant_updates(input_group_call_id)) { + need_update = false; + } if (need_update) { send_update_group_call(group_call, "on_get_group_call_participants"); } @@ -944,13 +949,24 @@ void GroupCallManager::on_update_group_call_participants( } auto *group_call_participants = add_group_call_participants(input_group_call_id); - auto &pending_updates = group_call_participants->pending_updates_[version]; - if (participants.size() <= pending_updates.size()) { - LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in " - << input_group_call_id; - return; + auto &pending_mute_updates = group_call_participants->pending_mute_updates_[version]; + vector> version_updates; + for (auto &participant : participants) { + if (GroupCallParticipant::is_versioned_update(participant)) { + version_updates.push_back(std::move(participant)); + } else { + pending_mute_updates.push_back(std::move(participant)); + } + } + if (!version_updates.empty()) { + auto &pending_version_updates = group_call_participants->pending_version_updates_[version]; + if (version_updates.size() <= pending_version_updates.size()) { + LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in " + << input_group_call_id; + return; + } + pending_version_updates = std::move(version_updates); } - pending_updates = std::move(participants); process_pending_group_call_participant_updates(input_group_call_id); } @@ -964,7 +980,6 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup if (participants_it == group_call_participants_.end()) { return false; } - auto &pending_updates = participants_it->second->pending_updates_; auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); if (group_call->version == -1 || !group_call->is_active) { @@ -974,31 +989,27 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup int32 diff = 0; bool is_left = false; bool need_rejoin = true; - while (!pending_updates.empty()) { - auto it = pending_updates.begin(); + auto &pending_version_updates = participants_it->second->pending_version_updates_; + while (!pending_version_updates.empty()) { + auto it = pending_version_updates.begin(); auto version = it->first; auto &participants = it->second; if (version <= group_call->version) { for (auto &group_call_participant : participants) { GroupCallParticipant participant(group_call_participant); on_participant_speaking_in_group_call(input_group_call_id, participant); - if (participant.user_id == td_->contacts_manager_->get_my_id()) { + if (participant.user_id == td_->contacts_manager_->get_my_id() && version == group_call->version && + participant.is_just_joined) { process_group_call_participant(input_group_call_id, std::move(participant)); } } LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in " << input_group_call_id << " from " << group_call->dialog_id; - pending_updates.erase(it); + pending_version_updates.erase(it); continue; } - if (version < group_call->version + static_cast(participants.size())) { - LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version - << ", but current version is " << group_call->version; - sync_group_call_participants(input_group_call_id); - break; - } - if (version == group_call->version + static_cast(participants.size())) { + if (version == group_call->version + 1) { group_call->version = version; for (auto &participant : participants) { GroupCallParticipant group_call_participant(participant); @@ -1011,7 +1022,7 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup } diff += process_group_call_participant(input_group_call_id, std::move(group_call_participant)); } - pending_updates.erase(it); + pending_version_updates.erase(it); } else if (!group_call->syncing_participants) { // found a gap LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version @@ -1020,7 +1031,27 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup break; } } - if (pending_updates.empty()) { + + auto &pending_mute_updates = participants_it->second->pending_mute_updates_; + while (!pending_mute_updates.empty()) { + auto it = pending_mute_updates.begin(); + auto version = it->first; + if (version <= group_call->version) { + auto &participants = it->second; + for (auto &group_call_participant : participants) { + GroupCallParticipant participant(group_call_participant); + on_participant_speaking_in_group_call(input_group_call_id, participant); + int mute_diff = process_group_call_participant(input_group_call_id, std::move(participant)); + CHECK(mute_diff == 0); + } + pending_mute_updates.erase(it); + continue; + } + on_receive_group_call_version(input_group_call_id, version); + break; + } + + if (pending_version_updates.empty() && pending_mute_updates.empty()) { sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get()); } @@ -1974,8 +2005,9 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou } // found a gap + LOG(INFO) << "Receive version " << version << " for group call " << input_group_call_id; auto *group_call_participants = add_group_call_participants(input_group_call_id); - group_call_participants->pending_updates_[version]; // reserve place for updates + group_call_participants->pending_version_updates_[version]; // reserve place for updates sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0); } diff --git a/td/telegram/GroupCallParticipant.cpp b/td/telegram/GroupCallParticipant.cpp index 39f11f2b2..95a3cbb7a 100644 --- a/td/telegram/GroupCallParticipant.cpp +++ b/td/telegram/GroupCallParticipant.cpp @@ -30,6 +30,10 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptrjust_joined_; } +bool GroupCallParticipant::is_versioned_update(const tl_object_ptr &participant) { + return participant->just_joined_ || participant->left_ || participant->versioned_; +} + bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) { bool new_can_be_muted = false; bool new_can_be_unmuted = false; diff --git a/td/telegram/GroupCallParticipant.h b/td/telegram/GroupCallParticipant.h index c78531e2f..77199ea01 100644 --- a/td/telegram/GroupCallParticipant.h +++ b/td/telegram/GroupCallParticipant.h @@ -20,10 +20,10 @@ class ContactsManager; struct GroupCallParticipant { UserId user_id; int32 source = 0; - bool is_muted = false; - bool can_self_unmute = false; int32 joined_date = 0; int32 active_date = 0; + bool is_muted = false; + bool can_self_unmute = false; bool can_be_muted = false; bool can_be_unmuted = false; @@ -37,6 +37,8 @@ struct GroupCallParticipant { explicit GroupCallParticipant(const tl_object_ptr &participant); + static bool is_versioned_update(const tl_object_ptr &participant); + bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin); int64 get_real_order() const { diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index c85e23b76..bb0e6e26b 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -10651,7 +10651,7 @@ void MessagesManager::delete_dialog(DialogId dialog_id) { close_dialog(d); } -void MessagesManager::reload_dialog_group_call(DialogId dialog_id) { +void MessagesManager::on_update_dialog_group_call_rights(DialogId dialog_id) { if (td_->auth_manager_->is_bot()) { return; } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index f0b7742e8..d8471b8ac 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -397,7 +397,7 @@ class MessagesManager : public Actor { void delete_dialog(DialogId dialog_id); - void reload_dialog_group_call(DialogId dialog_id); + void on_update_dialog_group_call_rights(DialogId dialog_id); void read_all_dialog_mentions(DialogId dialog_id, Promise &&promise); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 95b046302..4a48c12dd 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3895,6 +3895,9 @@ class CliClient final : public Actor { } else if (status_str == "addadmin") { status = td_api::make_object("anon", false, false, false, false, false, false, false, false, true, false, false); + } else if (status_str == "calladmin") { + status = td_api::make_object("anon", false, false, false, false, false, + false, false, false, false, true, false); } else if (status_str == "admin") { status = td_api::make_object("", true, true, true, true, true, true, true, true, true, false, false); From 3413e38a6196f774f41572ab2b942e7015d5f0c2 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 18 Dec 2020 16:48:49 +0300 Subject: [PATCH 18/29] Fix can_be_muted flag. --- td/telegram/ContactsManager.cpp | 6 ++++-- td/telegram/GroupCallManager.cpp | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 220e50996..e86451de0 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -11722,7 +11722,8 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti } } if (need_reload_group_call) { - td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(chat_id)); + send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights, + DialogId(chat_id)); } c->is_changed = true; @@ -12064,7 +12065,8 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id reload_dialog_administrators(DialogId(channel_id), 0, Auto()); } if (need_reload_group_call) { - td_->messages_manager_->on_update_dialog_group_call_rights(DialogId(channel_id)); + send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_group_call_rights, + DialogId(channel_id)); } } diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index a8f2083d1..46cd96623 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -426,6 +426,7 @@ struct GroupCallManager::GroupCallParticipants { string next_offset; int64 min_order = std::numeric_limits::max(); + bool are_administrators_loaded = false; vector administrator_user_ids; std::map>> pending_version_updates_; @@ -709,8 +710,10 @@ void GroupCallManager::on_update_group_call_rights(InputGroupCallId input_group_ auto participants_it = group_call_participants_.find(input_group_call_id); if (participants_it != group_call_participants_.end()) { CHECK(participants_it->second != nullptr); - update_group_call_participants_can_be_muted( - input_group_call_id, can_manage_group_calls(group_call->dialog_id).is_ok(), participants_it->second.get()); + if (participants_it->second->are_administrators_loaded) { + update_group_call_participants_can_be_muted( + input_group_call_id, can_manage_group_calls(group_call->dialog_id).is_ok(), participants_it->second.get()); + } } } @@ -1220,6 +1223,7 @@ void GroupCallManager::update_group_call_participants_can_be_muted(InputGroupCal bool can_manage, GroupCallParticipants *participants) { CHECK(participants != nullptr); + LOG(INFO) << "Update group call participants can_be_muted in " << input_group_call_id; for (auto &participant : participants->participants) { if (update_group_call_participant_can_be_muted(can_manage, participants, participant) && participant.order != 0) { send_update_group_call_participant(input_group_call_id, participant); @@ -1308,6 +1312,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou participant.order = real_order; } participant.is_just_joined = false; + update_group_call_participant_can_be_muted(can_manage, participants, participant); participants->participants.push_back(std::move(participant)); if (participants->participants.back().order != 0) { send_update_group_call_participant(input_group_call_id, participants->participants.back()); @@ -1408,6 +1413,7 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id, void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id) { if (!dialog_id.is_valid() || !need_group_call_participants(input_group_call_id) || can_manage_group_calls(dialog_id).is_error()) { + LOG(INFO) << "Don't need to load administrators in " << input_group_call_id << " from " << dialog_id; return; } @@ -1472,6 +1478,7 @@ void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId in } LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids; + group_call_participants->are_administrators_loaded = true; group_call_participants->administrator_user_ids = std::move(administrator_user_ids); update_group_call_participants_can_be_muted(input_group_call_id, true, group_call_participants); From 720a6ac45a3e6b9a56f575efc33041a25d6cdbd2 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 18 Dec 2020 17:21:25 +0300 Subject: [PATCH 19/29] Update .clang-format. --- .clang-format | 2 +- td/telegram/cli.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index 78d519b55..6ce3c0d61 100644 --- a/.clang-format +++ b/.clang-format @@ -92,7 +92,7 @@ PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Left +PointerAlignment: Right ReflowComments: false # true SortIncludes: false # disabled, because we need case insensitive sort SortUsingDeclarations: false # true diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4a48c12dd..cdd347f4b 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2845,7 +2845,8 @@ class CliClient final : public Actor { fingerprints.push_back(td_api::make_object("h2", "s2", "fingerprint2")); send_request(td_api::make_object( as_group_call_id(args), - td_api::make_object("ufrag", "pwd", std::move(fingerprints)), group_call_source_, true)); + td_api::make_object("ufrag", "pwd", std::move(fingerprints)), group_call_source_, + true)); } else if (op == "jgcc") { send_request(td_api::make_object(as_group_call_id(args), nullptr, 0, true)); } else if (op == "tgcmnp" || op == "tgcmnpe") { From 34cc9092c98b33761a2bac867af390818d352162 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 18 Dec 2020 17:43:23 +0300 Subject: [PATCH 20/29] Update layer 122. --- td/generate/scheme/telegram_api.tl | 2 +- td/generate/scheme/telegram_api.tlo | Bin 224340 -> 224380 bytes td/telegram/AnimationsManager.cpp | 3 ++- td/telegram/AudiosManager.cpp | 3 ++- td/telegram/DocumentsManager.cpp | 3 ++- td/telegram/StickersManager.cpp | 3 ++- td/telegram/VideoNotesManager.cpp | 3 ++- td/telegram/VideosManager.cpp | 2 +- td/telegram/VoiceNotesManager.cpp | 3 ++- 9 files changed, 14 insertions(+), 8 deletions(-) diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index 247f4c884..60018bf81 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -50,7 +50,7 @@ inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMe inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia; inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia; inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector stickers:flags.0?Vector ttl_seconds:flags.1?int = InputMedia; -inputMediaDocument#23ab23d2 flags:# id:InputDocument ttl_seconds:flags.0?int = InputMedia; +inputMediaDocument#33473058 flags:# id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia; inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia; inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia; inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index fa0b7fc553bb329c9f639223409398e6b758196f..f1cf1d522748fedb153c7b8abbe1df785ab04e5a 100644 GIT binary patch delta 470 zcmca|gZIx3-VHqbEX=W-S2hdqzc?)cV%$E*8^8jS?kGSc8Xg)ayHr-pmr~|SMWIG64mE($uFmN{(%FHV$E%8lF$xL*~PcF?(%`0I5yDFds zZ0B?tb!LId1@}cJKX@oIUEvlZ&*X+@GLs#AIUpAJJb=2f;K2ikNXSE|cN!knfJG)f zg1BKaOknbcM^H^4W=c$c^GF1uk>xSe3kms*hMQv_%QHg68=gSLAADgnn0(_2)Sf+0 zA%<*z@RSFt^20Nzxjla%!Lr%sxqvX(l;(tA+Y^2<{`mvuZBO{l)B({n9muShzQB}O fW_!a=CK*eJ`~oB99im|7bOBpNh3z#S%r}$)4A!uH delta 535 zcmex!gZIh}-VHqbES-K&k8Bp;e{os@#JYJ*$cF(4ik#VWIBeSvg2W~Z+|~dqn|$De z#pH(79FuEqH-H5u-BAG3(+gagZ6+t&aeydWaz_QiICIAY!eF@z716o703veXt`3;7 z>D~fH9gr;`TS4He99PUG<<-hUnRx}JCBCUCnTam>$)&lec_j=Wbzr-u7yM!pm|SpQ zWU|f!k;x9091ufG9w>0ae8DzZ@u~LYg#9ZfJNQDSYaT-UF+D(s(O|lb0He(0Gq=%< z(0BxK7d|yN9znc4`NK?!$s&(MAeQSqhWK&1Kp~^ylZ#B->q&2vcTZ7z8(APkn9enEvW9BU) RP?Za<80EJw@nF883;@B_@6!MP diff --git a/td/telegram/AnimationsManager.cpp b/td/telegram/AnimationsManager.cpp index c42e94856..de967e20b 100644 --- a/td/telegram/AnimationsManager.cpp +++ b/td/telegram/AnimationsManager.cpp @@ -346,7 +346,8 @@ tl_object_ptr AnimationsManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); diff --git a/td/telegram/AudiosManager.cpp b/td/telegram/AudiosManager.cpp index dd0bc539f..b8c57c30d 100644 --- a/td/telegram/AudiosManager.cpp +++ b/td/telegram/AudiosManager.cpp @@ -227,7 +227,8 @@ tl_object_ptr AudiosManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); diff --git a/td/telegram/DocumentsManager.cpp b/td/telegram/DocumentsManager.cpp index 96ddb6e7f..40d78bae8 100644 --- a/td/telegram/DocumentsManager.cpp +++ b/td/telegram/DocumentsManager.cpp @@ -582,7 +582,8 @@ tl_object_ptr DocumentsManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index c8199d333..1c37a6c60 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -2353,7 +2353,8 @@ tl_object_ptr StickersManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); diff --git a/td/telegram/VideoNotesManager.cpp b/td/telegram/VideoNotesManager.cpp index 1e525b067..e5c09bd4f 100644 --- a/td/telegram/VideoNotesManager.cpp +++ b/td/telegram/VideoNotesManager.cpp @@ -203,7 +203,8 @@ tl_object_ptr VideoNotesManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); diff --git a/td/telegram/VideosManager.cpp b/td/telegram/VideosManager.cpp index a3645e468..b054eae4f 100644 --- a/td/telegram/VideosManager.cpp +++ b/td/telegram/VideosManager.cpp @@ -256,7 +256,7 @@ tl_object_ptr VideosManager::get_input_media( flags |= telegram_api::inputMediaDocument::TTL_SECONDS_MASK; } return make_tl_object(flags, file_view.main_remote_location().as_input_document(), - ttl); + ttl, string()); } if (file_view.has_url()) { int32 flags = 0; diff --git a/td/telegram/VoiceNotesManager.cpp b/td/telegram/VoiceNotesManager.cpp index 59711ce43..0a7496154 100644 --- a/td/telegram/VoiceNotesManager.cpp +++ b/td/telegram/VoiceNotesManager.cpp @@ -170,7 +170,8 @@ tl_object_ptr VoiceNotesManager::get_input_media( return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0); + return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, + string()); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); From 905d09d82cc3cafeb7f672b2aece1d8ecce66b85 Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 19 Dec 2020 13:46:22 +0300 Subject: [PATCH 21/29] Accept non-lowercase end HTML tags. --- td/telegram/MessageEntity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/MessageEntity.cpp b/td/telegram/MessageEntity.cpp index 4f04dc17e..e60e29cba 100644 --- a/td/telegram/MessageEntity.cpp +++ b/td/telegram/MessageEntity.cpp @@ -2797,7 +2797,7 @@ static Result> do_parse_html(CSlice text, string &result) while (!is_space(text[i]) && text[i] != '>') { i++; } - Slice end_tag_name = text.substr(begin_pos + 2, i - begin_pos - 2); + string end_tag_name = to_lower(text.substr(begin_pos + 2, i - begin_pos - 2)); while (is_space(text[i]) && text[i] != 0) { i++; } From bbde4f32c62ef64e874fa2d5be21b48363b037ce Mon Sep 17 00:00:00 2001 From: levlam Date: Sat, 19 Dec 2020 14:31:42 +0300 Subject: [PATCH 22/29] Allow to specify emoji for sent stickers. --- td/generate/scheme/td_api.tl | 4 ++-- td/generate/scheme/td_api.tlo | Bin 191480 -> 191512 bytes td/telegram/MessageContent.cpp | 20 ++++++++++++++------ td/telegram/MessageContent.h | 9 ++++++--- td/telegram/MessagesManager.cpp | 24 +++++++++++++++++++----- td/telegram/MessagesManager.h | 2 ++ td/telegram/StickersManager.cpp | 14 +++++++++----- td/telegram/StickersManager.h | 3 ++- td/telegram/cli.cpp | 15 +++++++++------ 9 files changed, 63 insertions(+), 28 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 9f7708d1c..0c662a974 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1816,8 +1816,8 @@ inputMessageDocument document:InputFile thumbnail:inputThumbnail disable_content //@ttl Photo TTL (Time To Live), in seconds (0-60). A non-zero TTL can be specified only in private chats inputMessagePhoto photo:InputFile thumbnail:inputThumbnail added_sticker_file_ids:vector width:int32 height:int32 caption:formattedText ttl:int32 = InputMessageContent; -//@description A sticker message @sticker Sticker to be sent @thumbnail Sticker thumbnail, if available @width Sticker width @height Sticker height -inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 height:int32 = InputMessageContent; +//@description A sticker message @sticker Sticker to be sent @thumbnail Sticker thumbnail, if available @width Sticker width @height Sticker height @emoji Emoji used to choose the sticker +inputMessageSticker sticker:InputFile thumbnail:inputThumbnail width:int32 height:int32 emoji:string = InputMessageContent; //@description A video message @video Video to be sent @thumbnail Video thumbnail, if available @added_sticker_file_ids File identifiers of the stickers added to the video, if applicable //@duration Duration of the video, in seconds @width Video width @height Video height @supports_streaming True, if the video should be tried to be streamed diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 27d92657ef5833e24ac95a56accc365d79bd92a5..217e7fe7385510f7c8b137aee8f94e178a2e0aca 100644 GIT binary patch delta 706 zcmexyoqNU&?hPzrEKkJJ3O93znM{MQ9M(+H2D2tVc&M=X$MqSE2;P>PDoDIPw@i?D zA$OJ_@nr7lFd_8iJSc$3ZGP}D1W8rIV*@1KnkRdZcsy;x$Cm<_oVy7!5&+8KB^*99PWGZ6EE0GxG{cOMFv{ixbmRgG(}#vr~&;hO$oo z$jqn?HZkF?&Ey5!Stn2ZBt1DGoCD&36>njtzfFO<(&9amo2Jk0XOy0-aS`mO=`k9N z3ey$NGAc}7U z6arE6;FAhGY?vk=oUJ|C;uZkq zzCGeQ;{u44(-VT26t>G~Fe#{kWw$%{F~vZ%ZeQTfvTSAyh(!mn7%-`1>r#RQuZ=U(E|W6Z83TP delta 696 zcmbPngZsyI?hPzrEHi#?NZQOHW-<-Ja#%A(8_b&g;Gx3iAJ=CvB6wSFsvzu;`Kb^LGUK;c`gAqZrVvkoyjaO zVjyOxywCtMHcxn=09Cx@r3ysu&dV1N#)(%NoFG5mJSODBGC9#ndUDTIfyoD6s7&^F z4K-)QYlx=J7ha1n8iEuvK*3cxu9((Hbsgc%yn@ma-_+vb#PrnQlFa1n)FQZ{(*;== z)xjnvytSFUz={KE@mr{=AKs=wT^I2l$t~0O_A^RP*0>0E%=8)!Muq7PXBia`2B>_1 zcyDsRhdB@A`LK+6`w-DY9@VFfd>iGar8x)`0ajSA5@I@ttu2#K!3jK}-tU zZ8Vq^)WEXa6a1KBAX>K{@MqcsNgCUMsth1Zh=wa6OeN`H4PgHCoIOlmAlwPzK=WGm IGELC~02)GB2mk;8 diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 4f7c1e82e..cb6313dde 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -1594,6 +1594,7 @@ static Result create_input_message_content( unique_ptr content; UserId via_bot_user_id; int32 ttl = 0; + string emoji; bool is_bot = td->auth_manager_->is_bot(); switch (input_message_content->get_id()) { case td_api::inputMessageText::ID: { @@ -1709,6 +1710,9 @@ static Result create_input_message_content( } case td_api::inputMessageSticker::ID: { auto input_sticker = static_cast(input_message_content.get()); + + emoji = std::move(input_sticker->emoji_); + td->stickers_manager_->create_sticker(file_id, string(), thumbnail, get_dimensions(input_sticker->width_, input_sticker->height_), nullptr, false, nullptr); @@ -1967,7 +1971,8 @@ static Result create_input_message_content( default: UNREACHABLE(); } - return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl, via_bot_user_id}; + return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl, + via_bot_user_id, std::move(emoji)}; } Result get_input_message_content( @@ -2323,7 +2328,7 @@ static tl_object_ptr get_input_media_invoice(co static tl_object_ptr get_input_media_impl( const MessageContent *content, Td *td, tl_object_ptr input_file, - tl_object_ptr input_thumbnail, int32 ttl) { + tl_object_ptr input_thumbnail, int32 ttl, const string &emoji) { if (!can_have_input_media(td, content)) { return nullptr; } @@ -2381,7 +2386,8 @@ static tl_object_ptr get_input_media_impl( } case MessageContentType::Sticker: { auto m = static_cast(content); - return td->stickers_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail)); + return td->stickers_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail), + emoji); } case MessageContentType::Venue: { auto m = static_cast(content); @@ -2442,7 +2448,8 @@ tl_object_ptr get_input_media(const MessageContent *co bool force) { bool had_input_file = input_file != nullptr; bool had_input_thumbnail = input_thumbnail != nullptr; - auto input_media = get_input_media_impl(content, td, std::move(input_file), std::move(input_thumbnail), ttl); + auto input_media = + get_input_media_impl(content, td, std::move(input_file), std::move(input_thumbnail), ttl, string()); auto was_uploaded = FileManager::extract_was_uploaded(input_media); if (had_input_file) { if (!was_uploaded) { @@ -2471,8 +2478,9 @@ tl_object_ptr get_input_media(const MessageContent *co return input_media; } -tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl, bool force) { - auto input_media = get_input_media_impl(content, td, nullptr, nullptr, ttl); +tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl, + const string &emoji, bool force) { + auto input_media = get_input_media_impl(content, td, nullptr, nullptr, ttl, emoji); auto file_reference = FileManager::extract_file_reference(input_media); if (file_reference == FileReferenceView::invalid_file_reference()) { auto file_id = get_message_content_any_file_id(content); diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index 65d19c517..e66a4ce78 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -61,14 +61,16 @@ struct InputMessageContent { bool clear_draft = false; int32 ttl = 0; UserId via_bot_user_id; + string emoji; InputMessageContent(unique_ptr &&content, bool disable_web_page_preview, bool clear_draft, int32 ttl, - UserId via_bot_user_id) + UserId via_bot_user_id, string emoji) : content(std::move(content)) , disable_web_page_preview(disable_web_page_preview) , clear_draft(clear_draft) , ttl(ttl) - , via_bot_user_id(via_bot_user_id) { + , via_bot_user_id(via_bot_user_id) + , emoji(std::move(emoji)) { } }; @@ -112,7 +114,8 @@ tl_object_ptr get_input_media(const MessageContent *co FileId file_id, FileId thumbnail_file_id, int32 ttl, bool force); -tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl, bool force); +tl_object_ptr get_input_media(const MessageContent *content, Td *td, int32 ttl, + const string &emoji, bool force); void delete_message_content_thumbnail(MessageContent *content, Td *td); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index bb0e6e26b..8eff51f12 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4568,6 +4568,7 @@ void MessagesManager::Message::store(StorerT &storer) const { bool has_local_thread_message_ids = !local_thread_message_ids.empty(); bool has_linked_top_thread_message_id = linked_top_thread_message_id.is_valid(); bool has_interaction_info_update_date = interaction_info_update_date != 0; + bool has_send_emoji = !send_emoji.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_channel_post); STORE_FLAG(is_outgoing); @@ -4626,6 +4627,7 @@ void MessagesManager::Message::store(StorerT &storer) const { STORE_FLAG(has_linked_top_thread_message_id); STORE_FLAG(is_pinned); STORE_FLAG(has_interaction_info_update_date); + STORE_FLAG(has_send_emoji); END_STORE_FLAGS(); } @@ -4731,6 +4733,9 @@ void MessagesManager::Message::store(StorerT &storer) const { if (has_interaction_info_update_date) { store(interaction_info_update_date, storer); } + if (has_send_emoji) { + store(send_emoji, storer); + } store_message_content(content.get(), storer); if (has_reply_markup) { store(reply_markup, storer); @@ -4773,6 +4778,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool has_local_thread_message_ids = false; bool has_linked_top_thread_message_id = false; bool has_interaction_info_update_date = false; + bool has_send_emoji = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_channel_post); PARSE_FLAG(is_outgoing); @@ -4831,6 +4837,7 @@ void MessagesManager::Message::parse(ParserT &parser) { PARSE_FLAG(has_linked_top_thread_message_id); PARSE_FLAG(is_pinned); PARSE_FLAG(has_interaction_info_update_date); + PARSE_FLAG(has_send_emoji); END_PARSE_FLAGS(); } @@ -4942,6 +4949,9 @@ void MessagesManager::Message::parse(ParserT &parser) { if (has_interaction_info_update_date) { parse(interaction_info_update_date, parser); } + if (has_send_emoji) { + parse(send_emoji, parser); + } parse_message_content(content, parser); if (has_reply_markup) { parse(reply_markup, parser); @@ -22939,6 +22949,7 @@ Result MessagesManager::send_message(DialogId dialog_id, MessageId to m->ttl = message_content.ttl; m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type()); } + m->send_emoji = std::move(message_content.emoji); if (message_content.clear_draft) { if (top_thread_message_id.is_valid()) { @@ -23001,7 +23012,7 @@ Result MessagesManager::process_input_message_content( } return InputMessageContent(std::move(content), get_message_disable_web_page_preview(copied_message), false, 0, - UserId()); + UserId(), copied_message->send_emoji); } TRY_RESULT(content, get_input_message_content(dialog_id, std::move(input_message_content), td_)); @@ -23259,7 +23270,8 @@ void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vect on_secret_message_media_uploaded(dialog_id, m, std::move(secret_input_media), file_id, thumbnail_file_id); } } else { - auto input_media = get_input_media(content, td_, m->ttl, td_->auth_manager_->is_bot() && bad_parts.empty()); + auto input_media = + get_input_media(content, td_, m->ttl, m->send_emoji, td_->auth_manager_->is_bot() && bad_parts.empty()); if (input_media == nullptr) { if (content_type == MessageContentType::Game || content_type == MessageContentType::Poll) { return; @@ -23439,7 +23451,7 @@ void MessagesManager::on_upload_message_media_success(DialogId dialog_id, Messag update_message_content(dialog_id, m, std::move(content), true, true, true); - auto input_media = get_input_media(m->content.get(), td_, m->ttl, true); + auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true); Status result; if (input_media == nullptr) { result = Status::Error(400, "Failed to upload file"); @@ -23608,7 +23620,7 @@ void MessagesManager::do_send_message_group(int64 media_album_id) { } const FormattedText *caption = get_message_content_caption(m->content.get()); - auto input_media = get_input_media(m->content.get(), td_, m->ttl, true); + auto input_media = get_input_media(m->content.get(), td_, m->ttl, m->send_emoji, true); if (input_media == nullptr) { // TODO return CHECK auto file_id = get_message_content_any_file_id(m->content.get()); @@ -24819,7 +24831,7 @@ void MessagesManager::edit_inline_message_media(const string &inline_message_id, return promise.set_error(Status::Error(400, "Invalid inline message identifier specified")); } - auto input_media = get_input_media(content.content.get(), td_, 0, true); + auto input_media = get_input_media(content.content.get(), td_, 0, string(), true); if (input_media == nullptr) { return promise.set_error(Status::Error(400, "Invalid message content specified")); } @@ -25892,6 +25904,7 @@ Result> MessagesManager::resend_messages(DialogId dialog_id, v m->ttl = message->ttl; m->is_content_secret = message->is_content_secret; m->media_album_id = new_media_album_ids[message->media_album_id].first; + m->send_emoji = message->send_emoji; save_send_message_log_event(dialog_id, m); do_send_message(dialog_id, m); @@ -26142,6 +26155,7 @@ Result MessagesManager::add_local_message( m->ttl = message_content.ttl; } m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type()); + m->send_emoji = std::move(message_content.emoji); m->have_previous = true; m->have_next = true; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index d8471b8ac..755985daf 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1107,6 +1107,8 @@ class MessagesManager : public Actor { DialogId real_forward_from_dialog_id; // for resend_message MessageId real_forward_from_message_id; // for resend_message + string send_emoji; // for send_message + NotificationId notification_id; NotificationId removed_notification_id; diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index 1c37a6c60..287f4d2f3 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -2347,14 +2347,18 @@ SecretInputMedia StickersManager::get_secret_input_media(FileId sticker_file_id, tl_object_ptr StickersManager::get_input_media( FileId file_id, tl_object_ptr input_file, - tl_object_ptr input_thumbnail) const { + tl_object_ptr input_thumbnail, const string &emoji) const { auto file_view = td_->file_manager_->get_file_view(file_id); if (file_view.is_encrypted()) { return nullptr; } if (file_view.has_remote_location() && !file_view.main_remote_location().is_web() && input_file == nullptr) { - return make_tl_object(0, file_view.main_remote_location().as_input_document(), 0, - string()); + int32 flags = 0; + if (!emoji.empty()) { + flags |= telegram_api::inputMediaDocument::QUERY_MASK; + } + return make_tl_object(flags, file_view.main_remote_location().as_input_document(), + 0, emoji); } if (file_view.has_url()) { return make_tl_object(0, file_view.url(), 0); @@ -4757,7 +4761,7 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri void StickersManager::upload_sticker_file(UserId user_id, FileId file_id, Promise &&promise) { FileId upload_file_id; if (td_->file_manager_->get_file_view(file_id).get_type() == FileType::Sticker) { - CHECK(get_input_media(file_id, nullptr, nullptr) == nullptr); + CHECK(get_input_media(file_id, nullptr, nullptr, string()) == nullptr); upload_file_id = dup_sticker(td_->file_manager_->dup_file_id(file_id), file_id); } else { CHECK(td_->documents_manager_->get_input_media(file_id, nullptr, nullptr) == nullptr); @@ -4818,7 +4822,7 @@ void StickersManager::do_upload_sticker_file(UserId user_id, FileId file_id, bool is_animated = file_view.get_type() == FileType::Sticker; bool had_input_file = input_file != nullptr; - auto input_media = is_animated ? get_input_media(file_id, std::move(input_file), nullptr) + auto input_media = is_animated ? get_input_media(file_id, std::move(input_file), nullptr, string()) : td_->documents_manager_->get_input_media(file_id, std::move(input_file), nullptr); CHECK(input_media != nullptr); if (had_input_file && !FileManager::extract_was_uploaded(input_media)) { diff --git a/td/telegram/StickersManager.h b/td/telegram/StickersManager.h index d1ce49ef3..7cee2ca09 100644 --- a/td/telegram/StickersManager.h +++ b/td/telegram/StickersManager.h @@ -77,7 +77,8 @@ class StickersManager : public Actor { tl_object_ptr get_input_media(FileId file_id, tl_object_ptr input_file, - tl_object_ptr input_thumbnail) const; + tl_object_ptr input_thumbnail, + const string &emoji) const; SecretInputMedia get_secret_input_media(FileId sticker_file_id, tl_object_ptr input_file, diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index cdd347f4b..9305b7346 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3593,8 +3593,8 @@ class CliClient final : public Actor { string sticker_path; std::tie(chat_id, sticker_path) = split(args); - send_message(chat_id, - td_api::make_object(as_input_file(sticker_path), nullptr, 0, 0)); + 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; @@ -3602,14 +3602,17 @@ class CliClient final : public Actor { std::tie(chat_id, args) = split(args); std::tie(sticker_path, thumbnail_path) = split(args); - send_message(chat_id, td_api::make_object(as_input_file(sticker_path), - as_input_thumbnail(thumbnail_path), 0, 0)); + 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; - std::tie(chat_id, file_id) = split(args); + string emoji; + std::tie(chat_id, args) = split(args); + std::tie(file_id, emoji) = split(args); - send_message(chat_id, td_api::make_object(as_input_file_id(file_id), nullptr, 0, 0)); + send_message(chat_id, + td_api::make_object(as_input_file_id(file_id), nullptr, 0, 0, emoji)); } else if (op == "sv" || op == "svttl") { string chat_id; string video_path; From c2ac73769fe983043f473cb6e95afc1aca847b2f Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 20 Dec 2020 02:10:02 +0300 Subject: [PATCH 23/29] Fix self is_speaking flag. --- td/telegram/GroupCallManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 46cd96623..bcc712a43 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1688,7 +1688,7 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_ on_user_speaking_in_group_call(group_call_id, user_id, date, recursive); } - if (group_call->source == source && !group_call->dialog_id.is_valid() && group_call->is_speaking != is_speaking) { + if (group_call->source == source && group_call->dialog_id.is_valid() && group_call->is_speaking != is_speaking) { group_call->is_speaking = is_speaking; if (is_speaking) { pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 0.0); From fdf5b73db3b44a22a77e764d03eaaf75a99162ee Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 20 Dec 2020 14:08:03 +0300 Subject: [PATCH 24/29] Update documentation. --- td/generate/scheme/td_api.tl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0c662a974..7acae297c 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -719,7 +719,7 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r //@ttl_expires_in Time left before the message expires, in seconds //@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent //@author_signature For channel posts and anonymous group messages, optional author signature -//@media_album_id Unique identifier of an album this message belongs to. Only photos and videos can be grouped together in albums +//@media_album_id Unique identifier of an album this message belongs to. Only audios, documents, photos and videos can be grouped together in albums //@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted //@content Content of the message //@reply_markup Reply markup for the message; may be null From f11877f6ed95df131b4fac2621c3b1c4ea75f8e7 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 20 Dec 2020 14:08:11 +0300 Subject: [PATCH 25/29] Remove null messages from search-like request responses. --- td/telegram/MessagesManager.cpp | 40 ++++++++++++++++++++------------- td/telegram/MessagesManager.h | 8 ++++--- td/telegram/Td.cpp | 22 +++++++++--------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 8eff51f12..6e2008438 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -19910,8 +19910,8 @@ tl_object_ptr MessagesManager::get_dialog_history(DialogId dia } LOG(INFO) << "Return " << messages.size() << " messages in result to getChatHistory"; - promise.set_value(Unit()); // can return some messages - return get_messages_object(-1, std::move(messages)); // TODO return real total_count of messages in the dialog + promise.set_value(Unit()); // can return some messages + return get_messages_object(-1, std::move(messages), false); // TODO return real total_count of messages in the dialog } class MessagesManager::ReadHistoryOnServerLogEvent { @@ -22268,26 +22268,36 @@ tl_object_ptr MessagesManager::get_message_object(DialogId dial } tl_object_ptr MessagesManager::get_messages_object(int32 total_count, DialogId dialog_id, - const vector &message_ids) { + const vector &message_ids, + bool skip_not_found) { Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); - return get_messages_object(total_count, transform(message_ids, [this, dialog_id, d](MessageId message_id) { - return get_message_object(dialog_id, - get_message_force(d, message_id, "get_messages_object")); - })); + auto message_objects = transform(message_ids, [this, dialog_id, d](MessageId message_id) { + return get_message_object(dialog_id, get_message_force(d, message_id, "get_messages_object")); + }); + return get_messages_object(total_count, std::move(message_objects), skip_not_found); } tl_object_ptr MessagesManager::get_messages_object(int32 total_count, - const vector &full_message_ids) { - return get_messages_object(total_count, transform(full_message_ids, [this](FullMessageId full_message_id) { - return get_message_object(full_message_id); - })); + const vector &full_message_ids, + bool skip_not_found) { + auto message_objects = transform( + full_message_ids, [this](FullMessageId full_message_id) { return get_message_object(full_message_id); }); + return get_messages_object(total_count, std::move(message_objects), skip_not_found); } -tl_object_ptr MessagesManager::get_messages_object( - int32 total_count, vector> &&messages) { - if (total_count == -1) { - total_count = narrow_cast(messages.size()); +tl_object_ptr MessagesManager::get_messages_object(int32 total_count, + vector> &&messages, + bool skip_not_found) { + auto message_count = narrow_cast(messages.size()); + if (total_count < message_count) { + if (total_count != -1) { + LOG(ERROR) << "Have wrong total_count = " << total_count << ", while having " << message_count << " messages"; + } + total_count = message_count; + } + if (skip_not_found && td::remove(messages, nullptr)) { + total_count -= message_count - static_cast(messages.size()); } return td_api::make_object(total_count, std::move(messages)); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 755985daf..16c653ed9 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -787,9 +787,10 @@ class MessagesManager : public Actor { tl_object_ptr get_message_object(FullMessageId full_message_id); tl_object_ptr get_messages_object(int32 total_count, DialogId dialog_id, - const vector &message_ids); + const vector &message_ids, bool skip_not_found); - tl_object_ptr get_messages_object(int32 total_count, const vector &full_message_ids); + tl_object_ptr get_messages_object(int32 total_count, const vector &full_message_ids, + bool skip_not_found); void add_pending_update(tl_object_ptr &&update, int32 new_pts, int32 pts_count, bool force_apply, const char *source); @@ -2282,7 +2283,8 @@ class MessagesManager : public Actor { bool for_event_log = false) const; static tl_object_ptr get_messages_object(int32 total_count, - vector> &&messages); + vector> &&messages, + bool skip_not_found); vector sort_dialogs_by_order(const vector &dialog_ids, int32 limit) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index b90d74b29..f524e93bc 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1135,7 +1135,7 @@ class GetMessagesRequest : public RequestOnceActor { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_)); + send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_, false)); } public: @@ -1446,7 +1446,7 @@ class GetMessageThreadHistoryRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second)); + send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second, true)); } public: @@ -1483,7 +1483,7 @@ class SearchChatMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second)); + send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second, true)); } void do_send_error(Status &&status) override { @@ -1567,7 +1567,7 @@ class SearchMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second)); + send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second, true)); } void do_send_error(Status &&status) override { @@ -1612,7 +1612,7 @@ class SearchCallMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second)); + send_result(td->messages_manager_->get_messages_object(messages_.first, messages_.second, true)); } public: @@ -1639,7 +1639,7 @@ class SearchChatRecentLocationMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second)); + send_result(td->messages_manager_->get_messages_object(messages_.first, dialog_id_, messages_.second, true)); } public: @@ -1656,7 +1656,7 @@ class GetActiveLiveLocationMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(-1, full_message_ids_)); + send_result(td->messages_manager_->get_messages_object(-1, full_message_ids_, true)); } public: @@ -1724,7 +1724,7 @@ class GetChatScheduledMessagesRequest : public RequestActor<> { } void do_send_result() override { - send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_)); + send_result(td->messages_manager_->get_messages_object(-1, dialog_id_, message_ids_, true)); } public: @@ -5690,7 +5690,7 @@ void Td::on_request(uint64 id, td_api::sendMessageAlbum &request) { } send_closure(actor_id(this), &Td::send_result, id, - messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok())); + messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false)); } void Td::on_request(uint64 id, td_api::sendBotStartMessage &request) { @@ -5887,7 +5887,7 @@ void Td::on_request(uint64 id, td_api::forwardMessages &request) { } send_closure(actor_id(this), &Td::send_result, id, - messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok())); + messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false)); } void Td::on_request(uint64 id, const td_api::resendMessages &request) { @@ -5899,7 +5899,7 @@ void Td::on_request(uint64 id, const td_api::resendMessages &request) { } send_closure(actor_id(this), &Td::send_result, id, - messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok())); + messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok(), false)); } void Td::on_request(uint64 id, td_api::getWebPagePreview &request) { From 3b6c0143b6134800c8b90b73a85722ce9990eadf Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 21 Dec 2020 02:19:53 +0300 Subject: [PATCH 26/29] Improve error message. --- td/tl/tl_object_parse.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/td/tl/tl_object_parse.h b/td/tl/tl_object_parse.h index f61b9b96b..bd32dfe10 100644 --- a/td/tl/tl_object_parse.h +++ b/td/tl/tl_object_parse.h @@ -8,6 +8,7 @@ #include "td/tl/TlObject.h" +#include "td/utils/logging.h" #include "td/utils/UInt.h" #include @@ -21,8 +22,10 @@ class TlFetchBoxed { public: template static auto parse(ParserT &parser) -> decltype(Func::parse(parser)) { - if (parser.fetch_int() != constructor_id) { - parser.set_error("Wrong constructor found"); + auto parsed_constructor_id = parser.fetch_int(); + if (parsed_constructor_id != constructor_id) { + parser.set_error(PSTRING() << "Wrong constructor " << parsed_constructor_id << " found instead of " + << constructor_id); return decltype(Func::parse(parser))(); } return Func::parse(parser); From a640fb2fe084110532bb3db03c17714d51897a00 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 21 Dec 2020 03:02:03 +0300 Subject: [PATCH 27/29] Add to_string method for vector of TL objects. --- td/generate/DoxygenTlDocumentationGenerator.php | 15 +++++++++++++-- td/generate/tl_writer_h.cpp | 14 ++++++++++++++ td/telegram/GroupCallManager.cpp | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/td/generate/DoxygenTlDocumentationGenerator.php b/td/generate/DoxygenTlDocumentationGenerator.php index 8f727a047..5acffadf9 100644 --- a/td/generate/DoxygenTlDocumentationGenerator.php +++ b/td/generate/DoxygenTlDocumentationGenerator.php @@ -127,6 +127,7 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator return empty($tline) || $tline[0] === '}' || $tline === 'public:' || strpos($line, '#pragma ') === 0 || strpos($line, '#include <') === 0 || strpos($tline, 'return ') === 0 || strpos($tline, 'namespace') === 0 || preg_match('/class [A-Za-z0-9_]*;/', $line) || $tline === 'if (value == nullptr) {' || + strpos($tline, 'result += ') === 0 || strpos($tline, 'result = ') || strpos($tline, ' : values') || strpos($line, 'JNIEnv') || strpos($line, 'jfieldID') || $tline === 'virtual ~Object() {' || $tline === 'virtual void store(TlStorerToString &s, const char *field_name) const = 0;'; } @@ -294,7 +295,7 @@ EOT $this->addDocumentation('std::string to_string(const BaseObject &value);', <<addDocumentation('std::string to_string(const object_ptr &value) {', <<addDocumentation('std::string to_string(const std::vector> &values) {', <<addDocumentation(' void store(TlStorerToString &s, const char *field_name) const final;', <<\n" + "std::string to_string(const std::vector> &values) {\n" + " std::string result = \"{\\n\";\n" + " for (const auto &value : values) {\n" + " if (value == nullptr) {\n" + " result += \"null\\n\";\n" + " } else {\n" + " result += to_string(*value);\n" + " }\n" + " }\n" + " result += \"}\\n\";\n" + " return result;\n" "}\n\n"; } diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index bcc712a43..9eec77eb9 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -927,7 +927,7 @@ void GroupCallManager::on_update_group_call_participants( group_call->participant_count += diff; if (group_call->participant_count < 0) { LOG(ERROR) << "Participant count became negative in " << input_group_call_id << " from " - << group_call->dialog_id; + << group_call->dialog_id << " after applying " << to_string(participants); group_call->participant_count = 0; } update_group_call_dialog(group_call, "on_update_group_call_participants"); From 956e70d841731d5a7bae6bba0c1aba7f6de02308 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 21 Dec 2020 13:47:19 +0300 Subject: [PATCH 28/29] Add groupCall.can_be_managed flag. --- td/generate/scheme/td_api.tl | 5 +++-- td/generate/scheme/td_api.tlo | Bin 191512 -> 191552 bytes td/telegram/GroupCallManager.cpp | 24 +++++++++++++++++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 7acae297c..e8dac7221 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2071,14 +2071,15 @@ callStateError error:error = CallState; //@is_active True, if the call is active //@is_joined True, if the call is joined //@need_rejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined -//@can_unmute_self True, if the user can unmute themself +//@can_unmute_self True, if the current user can unmute themself +//@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 //@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 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_speaker_user_ids: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 217e7fe7385510f7c8b137aee8f94e178a2e0aca..c92950cd4f574c4b75076ffba2bd597db5e70f80 100644 GIT binary patch delta 123 zcmbPngZsb@?hO(`EHWGahHaJ+(pV-5VsWMy<(C#XC+6fZFo5_sj|utkOfK|Np4_lw z%Jd6@j2x`FiFt|XlM{oaH;e4FU9SAHJCTO;5wti_A_4@FO-4#lQ$Gt NfEnBGm&C6~#j9su$7C9?nk diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 9eec77eb9..33761ef2e 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -410,6 +410,7 @@ struct GroupCallManager::GroupCall { bool is_being_left = false; bool is_speaking = false; bool can_self_unmute = false; + bool can_be_managed = false; bool syncing_participants = false; bool loaded_all_participants = false; bool mute_new_participants = false; @@ -702,8 +703,8 @@ void GroupCallManager::get_group_call(GroupCallId group_call_id, } void GroupCallManager::on_update_group_call_rights(InputGroupCallId input_group_call_id) { + auto group_call = get_group_call(input_group_call_id); if (need_group_call_participants(input_group_call_id)) { - auto group_call = get_group_call(input_group_call_id); CHECK(group_call != nullptr && group_call->is_inited); try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); @@ -717,6 +718,14 @@ void GroupCallManager::on_update_group_call_rights(InputGroupCallId input_group_ } } + if (group_call != nullptr && group_call->is_inited) { + bool can_be_managed = group_call->is_active && can_manage_group_calls(group_call->dialog_id).is_ok(); + if (can_be_managed != group_call->can_be_managed) { + group_call->can_be_managed = can_be_managed; + send_update_group_call(group_call, "on_update_group_call_rights"); + } + } + reload_group_call(input_group_call_id, Auto()); } @@ -1809,6 +1818,7 @@ void GroupCallManager::on_group_call_left_impl(GroupCall *group_call, bool need_ group_call->is_being_left = false; group_call->is_speaking = false; group_call->can_self_unmute = false; + group_call->can_be_managed = false; group_call->joined_date = 0; group_call->source = 0; group_call->loaded_all_participants = false; @@ -1910,8 +1920,8 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptrgroup_call_id; call.dialog_id = dialog_id.is_valid() ? dialog_id : group_call->dialog_id; - call.can_self_unmute = - call.is_active && (!call.mute_new_participants || can_manage_group_calls(call.dialog_id).is_ok()); + call.can_be_managed = call.is_active && can_manage_group_calls(call.dialog_id).is_ok(); + call.can_self_unmute = (call.is_active && !call.mute_new_participants) || call.can_be_managed; if (!group_call->dialog_id.is_valid()) { group_call->dialog_id = dialog_id; } @@ -1955,6 +1965,10 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptrallowed_change_mute_new_participants = call.allowed_change_mute_new_participants; need_update = true; } + if (call.can_be_managed != group_call->can_be_managed) { + group_call->can_be_managed = call.can_be_managed; + need_update = true; + } if (call.version > group_call->version) { if (group_call->version != -1) { // if we know group call version, then update participants only by corresponding updates @@ -2232,8 +2246,8 @@ tl_object_ptr GroupCallManager::get_group_call_object(const G 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->participant_count, group_call->loaded_all_participants, - std::move(recent_speaker_user_ids), group_call->mute_new_participants, + 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->allowed_change_mute_new_participants, group_call->duration); } From 7d731265066c4c76c37115fda924f44987a90713 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 21 Dec 2020 22:06:52 +0300 Subject: [PATCH 29/29] Add success promise to on_get_updates. --- td/telegram/CallActor.cpp | 4 +- td/telegram/ContactsManager.cpp | 109 +++-- td/telegram/ContactsManager.h | 5 +- td/telegram/GroupCallManager.cpp | 43 +- td/telegram/MessagesManager.cpp | 62 +-- td/telegram/Payments.cpp | 10 +- td/telegram/PollManager.cpp | 8 +- td/telegram/Td.cpp | 2 +- td/telegram/UpdatesManager.cpp | 688 ++++++++++++++++++++----------- td/telegram/UpdatesManager.h | 259 +++++++----- 10 files changed, 711 insertions(+), 479 deletions(-) diff --git a/td/telegram/CallActor.cpp b/td/telegram/CallActor.cpp index 0ca317618..81a4968c5 100644 --- a/td/telegram/CallActor.cpp +++ b/td/telegram/CallActor.cpp @@ -310,7 +310,7 @@ void CallActor::on_set_rating_query_result(NetQueryPtr net_query) { return on_error(res.move_as_error()); } call_state_.need_rating = false; - send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok()); + send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok(), Promise()); } void CallActor::send_call_debug_information(string data, Promise<> promise) { @@ -730,7 +730,7 @@ void CallActor::on_discard_query_result(NetQueryPtr net_query) { if (res.is_error()) { return on_error(res.move_as_error()); } - send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok()); + send_closure(G()->updates_manager(), &UpdatesManager::on_get_updates, res.move_as_ok(), Promise()); } void CallActor::flush_call_state() { diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index e86451de0..9aed8083e 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -424,9 +424,7 @@ class AddContactQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for AddContactQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -457,9 +455,7 @@ class AcceptContactQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for AcceptContactQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -591,9 +587,7 @@ class DeleteContactsQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for DeleteContactsQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1140,9 +1134,7 @@ class ToggleChannelSignaturesQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for ToggleChannelSignaturesQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1185,10 +1177,17 @@ class ToggleChannelIsAllHistoryAvailableQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for TogglePreHistoryHiddenQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - td->contacts_manager_->on_update_channel_is_all_history_available(channel_id_, is_all_history_available_); - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates( + std::move(ptr), + PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_, + is_all_history_available = is_all_history_available_](Unit result) mutable { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_is_all_history_available, + channel_id, is_all_history_available, std::move(promise)); + })); } void on_error(uint64 id, Status status) override { @@ -1372,15 +1371,21 @@ class ToggleSlowModeQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_); - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates( + std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_, + slow_mode_delay = slow_mode_delay_](Unit result) mutable { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } + send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_slow_mode_delay, channel_id, + slow_mode_delay, std::move(promise)); + })); } void on_error(uint64 id, Status status) override { if (status.message() == "CHAT_NOT_MODIFIED") { - td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_); + td->contacts_manager_->on_update_channel_slow_mode_delay(channel_id_, slow_mode_delay_, Promise()); if (!td->auth_manager_->is_bot()) { promise_.set_value(Unit()); return; @@ -1456,9 +1461,7 @@ class DeleteChannelQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for DeleteChannelQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1487,9 +1490,7 @@ class AddChatUserQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for AddChatUserQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1667,10 +1668,13 @@ class ImportDialogInviteLinkQuery : public Td::ResultHandler { LOG(ERROR) << "Receive wrong result for ImportDialogInviteLinkQuery: " << to_string(ptr); return on_error(id, Status::Error(500, "Internal Server Error")); } + auto dialog_id = dialog_ids[0]; - td->updates_manager_->on_get_updates(std::move(ptr)); td->contacts_manager_->invalidate_invite_link_info(invite_link_); - promise_.set_value(std::move(dialog_ids[0])); + td->updates_manager_->on_get_updates( + std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), dialog_id](Unit) mutable { + promise.set_value(std::move(dialog_id)); + })); } void on_error(uint64 id, Status status) override { @@ -1699,9 +1703,7 @@ class DeleteChatUserQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for DeleteChatUserQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1733,9 +1735,7 @@ class JoinChannelQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for JoinChannelQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1769,10 +1769,8 @@ class InviteToChannelQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for InviteToChannelQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1806,10 +1804,8 @@ class EditChannelAdminQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelAdminQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1843,10 +1839,8 @@ class EditChannelBannedQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelBannedQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1879,9 +1873,7 @@ class LeaveChannelQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for LeaveChannelQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1953,10 +1945,8 @@ class EditChannelCreatorQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditChannelCreatorQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); td->contacts_manager_->invalidate_channel_full(channel_id_, false, false); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1985,9 +1975,7 @@ class MigrateChatQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for MigrateChatQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -12168,12 +12156,17 @@ void ContactsManager::on_update_channel_location(ChannelId channel_id, const Dia } } -void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay) { +void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay, + Promise &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } auto channel_full = get_channel_full_force(channel_id, "on_update_channel_slow_mode_delay"); if (channel_full != nullptr) { on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0); update_channel_full(channel_full, channel_id); } + promise.set_value(Unit()); } void ContactsManager::on_update_channel_slow_mode_next_send_date(ChannelId channel_id, int32 slow_mode_next_send_date) { @@ -12210,17 +12203,19 @@ void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_f } } -void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available) { +void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available, + Promise &&promise) { + if (G()->close_flag()) { + return promise.set_error(Status::Error(500, "Request aborted")); + } CHECK(channel_id.is_valid()); auto channel_full = get_channel_full_force(channel_id, "on_update_channel_is_all_history_available"); - if (channel_full == nullptr) { - return; - } - if (channel_full->is_all_history_available != is_all_history_available) { + if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) { channel_full->is_all_history_available = is_all_history_available; channel_full->is_changed = true; update_channel_full(channel_full, channel_id); } + promise.set_value(Unit()); } void ContactsManager::on_update_channel_default_permissions(ChannelId channel_id, diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 13bbe9034..c22151cf5 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -196,9 +196,10 @@ class ContactsManager : public Actor { void on_update_channel_sticker_set(ChannelId channel_id, StickerSetId sticker_set_id); void on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id); void on_update_channel_location(ChannelId channel_id, const DialogLocation &location); - void on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay); + void on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay, Promise &&promise); void on_update_channel_slow_mode_next_send_date(ChannelId channel_id, int32 slow_mode_next_send_date); - void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available); + void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available, + Promise &&promise); void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions); void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count); void on_update_channel_participant(ChannelId channel_id, UserId user_id, int32 date, diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 33761ef2e..8d50a1751 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -16,6 +16,8 @@ #include "td/telegram/Td.h" #include "td/telegram/UpdatesManager.h" +#include "td/actor/MultiPromise.h" + #include "td/utils/JsonBuilder.h" #include "td/utils/Random.h" @@ -56,11 +58,12 @@ class CreateGroupCallQuery : public Td::ResultHandler { LOG(ERROR) << "Receive wrong CreateGroupCallQuery response " << to_string(ptr); return on_error(id, Status::Error(500, "Receive wrong response")); } + auto group_call_id = group_call_ids[0]; - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(std::move(group_call_ids[0])); + td->updates_manager_->on_get_updates( + std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), group_call_id](Unit) mutable { + promise.set_value(std::move(group_call_id)); + })); } void on_error(uint64 id, Status status) override { @@ -224,10 +227,7 @@ class ToggleGroupCallSettingsQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for ToggleGroupCallSettingsQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -255,10 +255,7 @@ class InviteToGroupCallQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for InviteToGroupCallQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -294,10 +291,7 @@ class EditGroupCallMemberQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditGroupCallMemberQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -358,10 +352,7 @@ class LeaveGroupCallQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for LeaveGroupCallQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -389,10 +380,7 @@ class DiscardGroupCallQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for DiscardGroupCallQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - // TODO set promise after updates are processed - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1503,9 +1491,10 @@ void GroupCallManager::process_join_group_call_response(InputGroupCallId input_g } LOG(INFO) << "Receive result for JoinGroupCallQuery: " << to_string(updates); - td_->updates_manager_->on_get_updates(std::move(updates)); - - promise.set_error(Status::Error(500, "Wrong join response received")); + td_->updates_manager_->on_get_updates(std::move(updates), + PromiseCreator::lambda([promise = std::move(promise)](Unit) mutable { + promise.set_error(Status::Error(500, "Wrong join response received")); + })); } Result> GroupCallManager::get_group_call_join_response_object( diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 6e2008438..141bebb6a 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -243,7 +243,7 @@ class GetAllDraftsQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetAllDraftsQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); + td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } void on_error(uint64 id, Status status) override { @@ -610,9 +610,7 @@ class UpdateDialogPinnedMessageQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for UpdateDialogPinnedMessageQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1058,13 +1056,12 @@ class EditDialogPhotoQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditDialogPhotoQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); if (file_id_.is_valid() && was_uploaded_) { td->file_manager_->delete_partial_remote_location(file_id_); } - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1134,9 +1131,7 @@ class EditDialogTitleQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditDialogTitleQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -1178,9 +1173,7 @@ class EditDialogDefaultBannedRightsQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditDialogPermissionsQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -2338,9 +2331,7 @@ class BlockFromRepliesQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for BlockFromRepliesQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -2570,7 +2561,7 @@ class SendMessageActor : public NetActorOnce { auto constructor_id = ptr->get_id(); if (constructor_id != telegram_api::updateShortSentMessage::ID) { td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendMessage"); - return td->updates_manager_->on_get_updates(std::move(ptr)); + return td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } auto sent_message = move_tl_object_as(ptr); td->messages_manager_->on_update_sent_text_message(random_id_, std::move(sent_message->media_), @@ -2636,7 +2627,7 @@ class StartBotQuery : public Td::ResultHandler { LOG(INFO) << "Receive result for StartBotQuery for " << random_id_ << ": " << to_string(ptr); // Result may contain messageActionChatAddUser // td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "StartBot"); - td->updates_manager_->on_get_updates(std::move(ptr)); + td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } void on_error(uint64 id, Status status) override { @@ -2680,7 +2671,7 @@ class SendInlineBotResultQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for SendInlineBotResultQuery for " << random_id_ << ": " << to_string(ptr); td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendInlineBotResult"); - td->updates_manager_->on_get_updates(std::move(ptr)); + td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } void on_error(uint64 id, Status status) override { @@ -2773,7 +2764,7 @@ class SendMultiMediaActor : public NetActorOnce { td->updates_manager_->schedule_get_difference("Wrong sendMultiMedia result"); } - td->updates_manager_->on_get_updates(std::move(ptr)); + td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } void on_error(uint64 id, Status status) override { @@ -2867,7 +2858,7 @@ class SendMediaActor : public NetActorOnce { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for SendMediaQuery for " << random_id_ << ": " << to_string(ptr); td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendMedia"); - td->updates_manager_->on_get_updates(std::move(ptr)); + td->updates_manager_->on_get_updates(std::move(ptr), Promise()); } void on_error(uint64 id, Status status) override { @@ -3026,9 +3017,7 @@ class SendScheduledMessageActor : public NetActorOnce { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for SendScheduledMessageActor: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3102,9 +3091,7 @@ 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)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3220,9 +3207,7 @@ class SetGameScoreActor : public NetActorOnce { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for SetGameScoreActor: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3445,8 +3430,7 @@ class ForwardMessagesActor : public NetActorOnce { td->updates_manager_->schedule_get_difference("Wrong forwardMessages result"); } - td->updates_manager_->on_get_updates(std::move(ptr)); - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3494,8 +3478,7 @@ class SendScreenshotNotificationQuery : public Td::ResultHandler { LOG(INFO) << "Receive result for SendScreenshotNotificationQuery for " << random_id_ << ": " << to_string(ptr); td->messages_manager_->check_send_message_result(random_id_, dialog_id_, ptr.get(), "SendScreenshotNotificationQuery"); - td->updates_manager_->on_get_updates(std::move(ptr)); - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3706,9 +3689,7 @@ class DeleteScheduledMessagesQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for DeleteScheduledMessagesQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -3801,9 +3782,7 @@ class GetNotifySettingsExceptionsQuery : public Td::ResultHandler { for (auto &dialog_id : dialog_ids) { td->messages_manager_->force_create_dialog(dialog_id, "GetNotifySettingsExceptionsQuery"); } - td->updates_manager_->on_get_updates(std::move(updates_ptr)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(updates_ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -4185,8 +4164,7 @@ class EditPeerFoldersQuery : public Td::ResultHandler { auto ptr = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for EditPeerFoldersQuery: " << to_string(ptr); - td->updates_manager_->on_get_updates(std::move(ptr)); - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -29135,7 +29113,7 @@ void MessagesManager::on_create_new_dialog_success(int64 random_id, tl_object_pt return on_create_new_dialog_fail(random_id, Status::Error(500, "Chat was created earlier"), std::move(promise)); } - td_->updates_manager_->on_get_updates(std::move(updates)); + td_->updates_manager_->on_get_updates(std::move(updates), Promise()); } void MessagesManager::on_create_new_dialog_fail(int64 random_id, Status error, Promise &&promise) { diff --git a/td/telegram/Payments.cpp b/td/telegram/Payments.cpp index 17ee57e0c..984ac0270 100644 --- a/td/telegram/Payments.cpp +++ b/td/telegram/Payments.cpp @@ -361,8 +361,10 @@ class SendPaymentFormQuery : public Td::ResultHandler { switch (payment_result->get_id()) { case telegram_api::payments_paymentResult::ID: { auto result = move_tl_object_as(payment_result); - G()->td().get_actor_unsafe()->updates_manager_->on_get_updates(std::move(result->updates_)); - promise_.set_value(make_tl_object(true, string())); + td->updates_manager_->on_get_updates(std::move(result->updates_), + PromiseCreator::lambda([promise = std::move(promise_)](Unit) mutable { + promise.set_value(make_tl_object(true, string())); + })); return; } case telegram_api::payments_paymentVerificationNeeded::ID: { @@ -410,9 +412,7 @@ class GetPaymentReceiptQuery : public Td::ResultHandler { } promise_.set_value(make_tl_object( - payment_receipt->date_, - G()->td().get_actor_unsafe()->contacts_manager_->get_user_id_object(payments_provider_user_id, - "paymentReceipt"), + payment_receipt->date_, td->contacts_manager_->get_user_id_object(payments_provider_user_id, "paymentReceipt"), convert_invoice(std::move(payment_receipt->invoice_)), convert_order_info(std::move(payment_receipt->info_)), convert_shipping_option(std::move(payment_receipt->shipping_)), std::move(payment_receipt->credentials_title_))); diff --git a/td/telegram/PollManager.cpp b/td/telegram/PollManager.cpp index 4fec71262..db9340335 100644 --- a/td/telegram/PollManager.cpp +++ b/td/telegram/PollManager.cpp @@ -224,9 +224,7 @@ class StopPollActor : public NetActorOnce { auto result = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for StopPollQuery: " << to_string(result); - td->updates_manager_->on_get_updates(std::move(result)); - - promise_.set_value(Unit()); + td->updates_manager_->on_get_updates(std::move(result), std::move(promise_)); } void on_error(uint64 id, Status status) override { @@ -846,7 +844,7 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation, poll->was_saved = false; } if (result.is_ok()) { - td_->updates_manager_->on_get_updates(result.move_as_ok()); + td_->updates_manager_->on_get_updates(result.move_as_ok(), Promise()); for (auto &promise : promises) { promise.set_value(Unit()); @@ -1220,7 +1218,7 @@ void PollManager::on_get_poll_results(PollId poll_id, uint64 generation, return; } - td_->updates_manager_->on_get_updates(result.move_as_ok()); + td_->updates_manager_->on_get_updates(result.move_as_ok(), Promise()); } void PollManager::on_online() { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f524e93bc..de6233e5d 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3620,7 +3620,7 @@ void Td::on_result(NetQueryPtr query) { LOG(ERROR) << "Failed to fetch update: " << parser.get_error() << format::as_hex_dump<4>(ok.as_slice()); updates_manager_->schedule_get_difference("failed to fetch update"); } else { - updates_manager_->on_get_updates(std::move(ptr)); + updates_manager_->on_get_updates(std::move(ptr), Promise()); if (auth_manager_->is_bot() && auth_manager_->is_authorized()) { alarm_timeout_.set_timeout_in(PING_SERVER_ALARM_ID, PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5)); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index c8e3ac4ae..812cadc27 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -45,6 +45,8 @@ #include "td/telegram/TdDb.h" #include "td/telegram/WebPagesManager.h" +#include "td/actor/MultiPromise.h" + #include "td/utils/buffer.h" #include "td/utils/format.h" #include "td/utils/logging.h" @@ -64,16 +66,18 @@ class OnUpdate { UpdatesManager *manager_; tl_object_ptr &update_; bool force_apply_; + Promise &promise_; public: - OnUpdate(UpdatesManager *manager, tl_object_ptr &update, bool force_apply) - : manager_(manager), update_(update), force_apply_(force_apply) { + OnUpdate(UpdatesManager *manager, tl_object_ptr &update, bool force_apply, + Promise &promise) + : manager_(manager), update_(update), force_apply_(force_apply), promise_(promise) { } template void operator()(T &obj) const { CHECK(&*update_ == &obj); - manager_->on_update(move_tl_object_as(update_), force_apply_); + manager_->on_update(move_tl_object_as(update_), force_apply_, std::move(promise_)); } }; @@ -676,7 +680,14 @@ bool UpdatesManager::is_acceptable_update(const telegram_api::Update *update) co return true; } -void UpdatesManager::on_get_updates(tl_object_ptr &&updates_ptr) { +void UpdatesManager::on_get_updates(tl_object_ptr &&updates_ptr, Promise &&promise) { + promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { + if (!G()->close_flag() && result.is_error()) { + LOG(ERROR) << "Failed to process updates: " << result.error(); + } + promise.set_value(Unit()); + }); + CHECK(updates_ptr != nullptr); auto updates_type = updates_ptr->get_id(); if (updates_type != telegram_api::updateShort::ID) { @@ -687,7 +698,8 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat auto &update = static_cast(updates_ptr.get())->update_; auto update_id = update->get_id(); if (update_id == telegram_api::updateLoginToken::ID) { - return td_->auth_manager_->on_update_login_token(); + td_->auth_manager_->on_update_login_token(); + return promise.set_value(Unit()); } switch (update_id) { @@ -697,19 +709,20 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat case telegram_api::updateLangPackTooLong::ID: case telegram_api::updateLangPack::ID: LOG(INFO) << "Apply without authorization " << to_string(updates_ptr); - downcast_call(*update, OnUpdate(this, update, false)); + downcast_call(*update, OnUpdate(this, update, false, promise)); return; default: break; } } LOG(INFO) << "Ignore received before authorization or after logout " << to_string(updates_ptr); - return; + return promise.set_value(Unit()); } switch (updates_type) { case telegram_api::updatesTooLong::ID: get_difference("updatesTooLong"); + promise.set_value(Unit()); break; case telegram_api::updateShortMessage::ID: { auto update = move_tl_object_as(updates_ptr); @@ -725,17 +738,16 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat auto from_id = update->flags_ & MessagesManager::MESSAGE_FLAG_IS_OUT ? td_->contacts_manager_->get_my_id().get() : update->user_id_; update->flags_ |= MessagesManager::MESSAGE_FLAG_HAS_FROM_ID; + + auto message = make_tl_object( + update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, + false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, + make_tl_object(from_id), make_tl_object(update->user_id_), + std::move(update->fwd_from_), update->via_bot_id_, std::move(update->reply_to_), update->date_, + update->message_, nullptr, nullptr, std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()); on_pending_update( - make_tl_object( - make_tl_object( - update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - update->id_, make_tl_object(from_id), - make_tl_object(update->user_id_), std::move(update->fwd_from_), - update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_, nullptr, nullptr, - std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()), - update->pts_, update->pts_count_), - 0, "telegram_api::updatesShortMessage"); + make_tl_object(std::move(message), update->pts_, update->pts_count_), 0, + std::move(promise), "telegram_api::updatesShortMessage"); break; } case telegram_api::updateShortChatMessage::ID: { @@ -750,17 +762,16 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat } update->flags_ |= MessagesManager::MESSAGE_FLAG_HAS_FROM_ID; + auto message = make_tl_object( + update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, + false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_, + make_tl_object(update->from_id_), + make_tl_object(update->chat_id_), std::move(update->fwd_from_), update->via_bot_id_, + std::move(update->reply_to_), update->date_, update->message_, nullptr, nullptr, std::move(update->entities_), + 0, 0, nullptr, 0, string(), 0, Auto()); on_pending_update( - make_tl_object( - make_tl_object( - update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - update->id_, make_tl_object(update->from_id_), - make_tl_object(update->chat_id_), std::move(update->fwd_from_), - update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_, nullptr, nullptr, - std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()), - update->pts_, update->pts_count_), - 0, "telegram_api::updatesShortChatMessage"); + make_tl_object(std::move(message), update->pts_, update->pts_count_), 0, + std::move(promise), "telegram_api::updatesShortChatMessage"); break; } case telegram_api::updateShort::ID: { @@ -768,11 +779,12 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat LOG(DEBUG) << "Receive " << oneline(to_string(update)); if (!is_acceptable_update(update->update_.get())) { LOG(ERROR) << "Receive unacceptable short update: " << oneline(to_string(update)); + promise.set_value(Unit()); return get_difference("unacceptable short update"); } short_update_date_ = update->date_; - if (!downcast_call(*update->update_, OnUpdate(this, update->update_, false))) { - LOG(ERROR) << "Can't call on some update"; + if (!downcast_call(*update->update_, OnUpdate(this, update->update_, false, promise))) { + LOG(FATAL) << "Can't call on some update"; } short_update_date_ = 0; break; @@ -782,20 +794,21 @@ void UpdatesManager::on_get_updates(tl_object_ptr &&updat td_->contacts_manager_->on_get_users(std::move(updates->users_), "updatesCombined"); td_->contacts_manager_->on_get_chats(std::move(updates->chats_), "updatesCombined"); on_pending_updates(std::move(updates->updates_), updates->seq_start_, updates->seq_, updates->date_, - "telegram_api::updatesCombined"); + std::move(promise), "telegram_api::updatesCombined"); break; } case telegram_api::updates::ID: { auto updates = move_tl_object_as(updates_ptr); td_->contacts_manager_->on_get_users(std::move(updates->users_), "updates"); td_->contacts_manager_->on_get_chats(std::move(updates->chats_), "updates"); - on_pending_updates(std::move(updates->updates_), updates->seq_, updates->seq_, updates->date_, + on_pending_updates(std::move(updates->updates_), updates->seq_, updates->seq_, updates->date_, std::move(promise), "telegram_api::updates"); break; } case telegram_api::updateShortSentMessage::ID: LOG(ERROR) << "Receive " << oneline(to_string(updates_ptr)); get_difference("updateShortSentMessage"); + promise.set_value(Unit()); break; default: UNREACHABLE(); @@ -1050,17 +1063,17 @@ void UpdatesManager::process_get_difference_updates( auto constructor_id = update->get_id(); if (constructor_id == telegram_api::updateMessageID::ID) { // in getDifference updateMessageID can't be received for scheduled messages - on_update(move_tl_object_as(update), true); + on_update(move_tl_object_as(update), true, Promise()); CHECK(!running_get_difference_); } if (constructor_id == telegram_api::updateEncryption::ID) { - on_update(move_tl_object_as(update), true); + on_update(move_tl_object_as(update), true, Promise()); CHECK(!running_get_difference_); } if (constructor_id == telegram_api::updateFolderPeers::ID) { - on_update(move_tl_object_as(update), true); + on_update(move_tl_object_as(update), true, Promise()); CHECK(!running_get_difference_); } @@ -1068,7 +1081,7 @@ void UpdatesManager::process_get_difference_updates( // TODO can't apply it here, because dialog may not be created yet // process updateReadHistoryInbox before new messages if (constructor_id == telegram_api::updateReadHistoryInbox::ID) { - on_update(move_tl_object_as(update), true); + on_update(move_tl_object_as(update), true, Promise()); CHECK(!running_get_difference_); } */ @@ -1085,7 +1098,7 @@ void UpdatesManager::process_get_difference_updates( Promise()); } - process_updates(std::move(other_updates), true); + process_updates(std::move(other_updates), true, Promise()); } void UpdatesManager::on_get_difference(tl_object_ptr &&difference_ptr) { @@ -1106,10 +1119,16 @@ void UpdatesManager::on_get_difference(tl_object_ptrseq_; if (!pending_seq_updates_.empty()) { LOG(WARNING) << "Drop " << pending_seq_updates_.size() << " pending seq updates after receive empty difference"; + for (auto &pending_update : pending_seq_updates_) { + pending_update.second.promise.set_value(Unit()); + } pending_seq_updates_.clear(); } if (!pending_qts_updates_.empty()) { LOG(WARNING) << "Drop " << pending_qts_updates_.size() << " pending qts updates after receive empty difference"; + for (auto &pending_update : pending_qts_updates_) { + pending_update.second.promise.set_value(Unit()); + } pending_qts_updates_.clear(); } break; @@ -1194,9 +1213,11 @@ void UpdatesManager::after_get_difference() { auto updates = std::move(it->second.updates); auto updates_seq_begin = it->second.seq_begin; auto updates_seq_end = it->second.seq_end; + auto promise = std::move(it->second.promise); // ignore it->second.date, because it may be too old postponed_updates_.erase(it); - on_pending_updates(std::move(updates), updates_seq_begin, updates_seq_end, 0, "postponed updates"); + on_pending_updates(std::move(updates), updates_seq_begin, updates_seq_end, 0, std::move(promise), + "postponed updates"); if (running_get_difference_) { VLOG(get_difference) << "Finish to apply postponed updates with " << postponed_updates_.size() << " updates left, because forced to run getDifference"; @@ -1216,14 +1237,14 @@ void UpdatesManager::after_get_difference() { } void UpdatesManager::on_pending_updates(vector> &&updates, int32 seq_begin, - int32 seq_end, int32 date, const char *source) { + int32 seq_end, int32 date, Promise &&promise, const char *source) { if (get_pts() == -1) { init_state(); } if (!td_->auth_manager_->is_authorized()) { LOG(INFO) << "Ignore updates received before authorization or after logout"; - return; + return promise.set_value(Unit()); } // for (auto &update : updates) { @@ -1234,20 +1255,19 @@ void UpdatesManager::on_pending_updates(vector(update), false); + on_update(move_tl_object_as(update), false, mpas.get_promise()); processed_updates++; update = nullptr; } if (id == telegram_api::updateEncryption::ID) { - on_update(move_tl_object_as(update), false); + on_update(move_tl_object_as(update), false, mpas.get_promise()); processed_updates++; update = nullptr; } @@ -1373,8 +1399,9 @@ void UpdatesManager::on_pending_updates(vectorsecond.promise.set_value(Unit()); // TODO + } - pending_seq_updates_.emplace(seq_begin, PendingUpdates(seq_begin, seq_end, date, std::move(updates))); + pending_seq_updates_.emplace(seq_begin, + PendingUpdates(seq_begin, seq_end, date, std::move(updates), mpas.get_promise())); set_seq_gap_timeout(MAX_UNFILLED_GAP_TIME); + lock.set_value(Unit()); } -void UpdatesManager::add_pending_qts_update(tl_object_ptr &&update, int32 qts) { +void UpdatesManager::add_pending_qts_update(tl_object_ptr &&update, int32 qts, + Promise &&promise) { CHECK(update != nullptr); if (qts <= 1) { LOG(ERROR) << "Receive wrong qts " << qts << " in " << oneline(to_string(update)); + promise.set_value(Unit()); return; } @@ -1444,6 +1478,7 @@ void UpdatesManager::add_pending_qts_update(tl_object_ptr if (qts <= old_qts) { LOG(INFO) << "Skip already applied update with qts = " << qts; + promise.set_value(Unit()); return; } @@ -1454,19 +1489,28 @@ void UpdatesManager::add_pending_qts_update(tl_object_ptr if (pending_qts_updates_.empty()) { set_qts_gap_timeout(MAX_UNFILLED_GAP_TIME); } - bool is_inserted = pending_qts_updates_.emplace(qts, std::move(update)).second; - if (!is_inserted) { - LOG(INFO) << "Receive duplicate update with qts = " << qts; + auto &pending_update = pending_qts_updates_[qts]; + if (pending_update.update != nullptr) { + LOG(WARNING) << "Receive duplicate update with qts = " << qts; + pending_update.promise.set_value(Unit()); // TODO } + pending_update.update = std::move(update); + pending_update.promise = std::move(promise); return; } - process_qts_update(std::move(update), qts); + process_qts_update(std::move(update), qts, std::move(promise)); process_pending_qts_updates(); } -void UpdatesManager::process_updates(vector> &&updates, bool force_apply) { +void UpdatesManager::process_updates(vector> &&updates, bool force_apply, + Promise &&promise) { tl_object_ptr update_pts_changed; + + MultiPromiseActorSafe mpas{"OnPendingUpdatesMultiPromiseActor"}; + mpas.add_promise(std::move(promise)); + auto lock = mpas.get_promise(); + /* for (auto &update : updates) { if (update != nullptr) { @@ -1474,7 +1518,7 @@ void UpdatesManager::process_updates(vector> // process updateReadChannelInbox before updateNewChannelMessage auto constructor_id = update->get_id(); if (constructor_id == telegram_api::updateReadChannelInbox::ID) { - on_update(move_tl_object_as(update), force_apply); + on_update(move_tl_object_as(update), force_apply, mpas.get_promise()); } } } @@ -1484,12 +1528,12 @@ void UpdatesManager::process_updates(vector> // process updateNewChannelMessage first auto constructor_id = update->get_id(); if (constructor_id == telegram_api::updateNewChannelMessage::ID) { - on_update(move_tl_object_as(update), force_apply); + on_update(move_tl_object_as(update), force_apply, mpas.get_promise()); } // process updateNewScheduledMessage first if (constructor_id == telegram_api::updateNewScheduledMessage::ID) { - on_update(move_tl_object_as(update), force_apply); + on_update(move_tl_object_as(update), force_apply, mpas.get_promise()); } // updatePtsChanged forces get difference, so process it last @@ -1501,19 +1545,22 @@ void UpdatesManager::process_updates(vector> for (auto &update : updates) { if (update != nullptr) { LOG(INFO) << "Process update " << to_string(update); - if (!downcast_call(*update, OnUpdate(this, update, force_apply))) { - LOG(ERROR) << "Can't call on some update"; + auto update_promise = mpas.get_promise(); + if (!downcast_call(*update, OnUpdate(this, update, force_apply, update_promise))) { + LOG(FATAL) << "Can't call on some update"; } CHECK(!running_get_difference_); } } if (update_pts_changed != nullptr) { - on_update(std::move(update_pts_changed), force_apply); + on_update(std::move(update_pts_changed), force_apply, mpas.get_promise()); } + lock.set_value(Unit()); } void UpdatesManager::process_seq_updates(int32 seq_end, int32 date, - vector> &&updates) { + vector> &&updates, + Promise &&promise) { string serialized_updates = PSTRING() << "process_seq_updates [seq_ = " << seq_ << ", seq_end = " << seq_end << "]: "; // TODO remove after bugs will be fixed for (auto &update : updates) { @@ -1521,7 +1568,7 @@ void UpdatesManager::process_seq_updates(int32 seq_end, int32 date, serialized_updates += oneline(to_string(update)); } } - process_updates(std::move(updates), false); + process_updates(std::move(updates), false, std::move(promise)); if (seq_end) { seq_ = seq_end; } @@ -1530,7 +1577,8 @@ void UpdatesManager::process_seq_updates(int32 seq_end, int32 date, } } -void UpdatesManager::process_qts_update(tl_object_ptr &&update_ptr, int32 qts) { +void UpdatesManager::process_qts_update(tl_object_ptr &&update_ptr, int32 qts, + Promise &&promise) { LOG(DEBUG) << "Process " << to_string(update_ptr); switch (update_ptr->get_id()) { case telegram_api::updateNewEncryptedMessage::ID: { @@ -1550,6 +1598,7 @@ void UpdatesManager::process_qts_update(tl_object_ptr &&up UNREACHABLE(); break; } + promise.set_value(Unit()); } void UpdatesManager::process_pending_seq_updates() { @@ -1563,7 +1612,8 @@ void UpdatesManager::process_pending_seq_updates() { break; } if (seq_begin == seq_ + 1) { - process_seq_updates(update_it->second.seq_end, update_it->second.date, std::move(update_it->second.updates)); + process_seq_updates(update_it->second.seq_end, update_it->second.date, std::move(update_it->second.updates), + std::move(update_it->second.promise)); } else { // old update CHECK(seq_begin != 0); @@ -1594,7 +1644,7 @@ void UpdatesManager::process_pending_qts_updates() { break; } if (qts == get_qts() + 1) { - process_qts_update(std::move(update_it->second), qts); + process_qts_update(std::move(update_it->second.update), qts, std::move(update_it->second.promise)); } pending_qts_updates_.erase(update_it); } @@ -1622,26 +1672,29 @@ void UpdatesManager::set_qts_gap_timeout(double timeout) { } } -void UpdatesManager::on_pending_update(tl_object_ptr update, int32 seq, const char *source) { +void UpdatesManager::on_pending_update(tl_object_ptr update, int32 seq, Promise &&promise, + const char *source) { vector> updates; updates.push_back(std::move(update)); - on_pending_updates(std::move(updates), seq, seq, 0, source); + on_pending_updates(std::move(updates), seq, seq, 0, std::move(promise), source); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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, "on_updateNewMessage"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +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()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { if (!force_apply) { LOG(ERROR) << "Receive updateMessageID not in getDifference"; return; @@ -1649,26 +1702,29 @@ void UpdatesManager::on_update(tl_object_ptr upda LOG(INFO) << "Receive update about sent message " << to_string(update); td_->messages_manager_->on_update_message_id(update->random_id_, MessageId(ServerMessageId(update->id_)), "getDifference"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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, "on_updateReadMessagesContents"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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, "on_updateEditMessage"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; if (update->messages_.empty()) { @@ -1678,10 +1734,11 @@ void UpdatesManager::on_update(tl_object_ptr td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, "on_updateDeleteMessages"); } + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { int new_pts = update->pts_; int pts_count = update->pts_count_; if (force_apply) { @@ -1689,97 +1746,118 @@ void UpdatesManager::on_update(tl_object_ptrmessages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply, "on_updateReadHistoryInbox"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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, "on_updateReadHistoryOutbox"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_service_notification(std::move(update), true, Promise()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { // nothing to do + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_read_channel_inbox(std::move(update)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_read_channel_outbox(std::move(update)); + promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { + bool /*force_apply*/, Promise &&promise) { td_->messages_manager_->on_update_read_channel_messages_contents(std::move(update)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { td_->messages_manager_->on_update_channel_too_long(std::move(update), force_apply); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { if (!force_apply) { td_->contacts_manager_->invalidate_channel_full(ChannelId(update->channel_id_), false, false); } + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +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()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +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; - return; + } 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"); } - 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"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +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; - return; + } else { + DialogId dialog_id(channel_id); + td_->messages_manager_->on_update_message_view_count({dialog_id, MessageId(ServerMessageId(update->id_))}, + update->views_); } - DialogId dialog_id(channel_id); - td_->messages_manager_->on_update_message_view_count({dialog_id, MessageId(ServerMessageId(update->id_))}, - update->views_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +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; - return; + } else { + DialogId dialog_id(channel_id); + td_->messages_manager_->on_update_message_forward_count({dialog_id, MessageId(ServerMessageId(update->id_))}, + update->forwards_); } - DialogId dialog_id(channel_id); - td_->messages_manager_->on_update_message_forward_count({dialog_id, MessageId(ServerMessageId(update->id_))}, - update->forwards_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_channel_max_unavailable_message_id( ChannelId(update->channel_id_), MessageId(ServerMessageId(update->available_min_id_))); + promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { + bool /*force_apply*/, Promise &&promise) { td_->messages_manager_->on_update_read_message_comments( DialogId(ChannelId(update->channel_id_)), MessageId(ServerMessageId(update->top_msg_id_)), MessageId(), MessageId(ServerMessageId(update->read_max_id_)), MessageId()); @@ -1788,38 +1866,43 @@ void UpdatesManager::on_update(tl_object_ptrbroadcast_id_)), MessageId(ServerMessageId(update->broadcast_post_)), MessageId(), MessageId(ServerMessageId(update->read_max_id_)), MessageId()); } + promise.set_value(Unit()); } void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { + bool /*force_apply*/, Promise &&promise) { td_->messages_manager_->on_update_read_message_comments( DialogId(ChannelId(update->channel_id_)), MessageId(ServerMessageId(update->top_msg_id_)), MessageId(), MessageId(), MessageId(ServerMessageId(update->read_max_id_))); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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, "on_updatePinnedMessages"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +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; - return; + } 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"); } - 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"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { switch (update->peer_->get_id()) { case telegram_api::notifyPeer::ID: { DialogId dialog_id(static_cast(update->peer_.get())->peer_); @@ -1832,49 +1915,59 @@ void UpdatesManager::on_update(tl_object_ptr break; } case telegram_api::notifyUsers::ID: - return td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Private, - std::move(update->notify_settings_)); + td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Private, + std::move(update->notify_settings_)); + break; case telegram_api::notifyChats::ID: - return td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Group, - std::move(update->notify_settings_)); + td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Group, + std::move(update->notify_settings_)); + break; case telegram_api::notifyBroadcasts::ID: - return td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Channel, - std::move(update->notify_settings_)); + td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Channel, + std::move(update->notify_settings_)); + break; default: UNREACHABLE(); } + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_get_peer_settings(DialogId(update->peer_), std::move(update->settings_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_peer_located(std::move(update->peers_), true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +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()); td_->messages_manager_->add_pending_update(make_tl_object(), update->pts_, update->pts_count_, force_apply, "on_updateWebPage"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { - CHECK(update != nullptr); +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; - return; + } 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"); } - DialogId dialog_id(channel_id); - td_->messages_manager_->add_pending_channel_update(dialog_id, make_tl_object(), update->pts_, - update->pts_count_, "on_updateChannelWebPage"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { - CHECK(update != nullptr); +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { for (auto &folder_peer : update->folder_peers_) { DialogId dialog_id(folder_peer->peer_); FolderId folder_id(folder_peer->folder_id_); @@ -1883,6 +1976,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"); + promise.set_value(Unit()); } int32 UpdatesManager::get_short_update_date() const { @@ -1893,19 +1987,24 @@ int32 UpdatesManager::get_short_update_date() const { return now; } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { UserId user_id(update->user_id_); td_->messages_manager_->on_user_dialog_action(DialogId(user_id), MessageId(), user_id, DialogAction(std::move(update->action_)), get_short_update_date()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_user_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(), UserId(update->user_id_), DialogAction(std::move(update->action_)), get_short_update_date()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { MessageId top_thread_message_id; if ((update->flags_ & telegram_api::updateChannelUserTyping::TOP_MSG_ID_MASK) != 0) { top_thread_message_id = MessageId(ServerMessageId(update->top_msg_id_)); @@ -1913,245 +2012,331 @@ void UpdatesManager::on_update(tl_object_ptrmessages_manager_->on_user_dialog_action(DialogId(ChannelId(update->channel_id_)), top_thread_message_id, UserId(update->user_id_), DialogAction(std::move(update->action_)), get_short_update_date()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { SecretChatId secret_chat_id(update->chat_id_); UserId user_id = td_->contacts_manager_->get_secret_chat_user_id(secret_chat_id); td_->messages_manager_->on_user_dialog_action(DialogId(secret_chat_id), MessageId(), user_id, DialogAction::get_typing_action(), get_short_update_date()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_user_online(UserId(update->user_id_), std::move(update->status_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_user_name(UserId(update->user_id_), std::move(update->first_name_), std::move(update->last_name_), std::move(update->username_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_user_phone_number(UserId(update->user_id_), std::move(update->phone_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { // TODO update->previous_, update->date_ td_->contacts_manager_->on_update_user_photo(UserId(update->user_id_), std::move(update->photo_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_is_blocked(DialogId(update->peer_id_), update->blocked_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_get_chat_participants(std::move(update->participants_), true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_chat_add_user(ChatId(update->chat_id_), UserId(update->inviter_id_), UserId(update->user_id_), update->date_, update->version_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_chat_edit_administrator(ChatId(update->chat_id_), UserId(update->user_id_), update->is_admin_, update->version_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_chat_delete_user(ChatId(update->chat_id_), UserId(update->user_id_), update->version_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { DialogId dialog_id(update->peer_); RestrictedRights permissions = get_restricted_rights(std::move(update->default_banned_rights_)); auto version = update->version_; switch (dialog_id.get_type()) { + case DialogType::Chat: + td_->contacts_manager_->on_update_chat_default_permissions(dialog_id.get_chat_id(), permissions, version); + break; + case DialogType::Channel: + LOG_IF(ERROR, version != 0) << "Receive version " << version << " in " << dialog_id; + td_->contacts_manager_->on_update_channel_default_permissions(dialog_id.get_channel_id(), permissions); + break; case DialogType::None: case DialogType::User: case DialogType::SecretChat: default: LOG(ERROR) << "Receive updateChatDefaultBannedRights in the " << dialog_id; - return; - case DialogType::Chat: - return td_->contacts_manager_->on_update_chat_default_permissions(dialog_id.get_chat_id(), permissions, version); - case DialogType::Channel: { - LOG_IF(ERROR, version != 0) << "Receive version " << version << " in " << dialog_id; - return td_->contacts_manager_->on_update_channel_default_permissions(dialog_id.get_channel_id(), permissions); - } + break; } + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_draft_message(DialogId(update->peer_), std::move(update->draft_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { FolderId folder_id(update->flags_ & telegram_api::updateDialogPinned::FOLDER_ID_MASK ? update->folder_id_ : 0); td_->messages_manager_->on_update_dialog_is_pinned( folder_id, DialogId(update->peer_), (update->flags_ & telegram_api::updateDialogPinned::PINNED_MASK) != 0); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { FolderId folder_id(update->flags_ & telegram_api::updatePinnedDialogs::FOLDER_ID_MASK ? update->folder_id_ : 0); td_->messages_manager_->on_update_pinned_dialogs(folder_id); // TODO use update->order_ + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_is_marked_as_unread( DialogId(update->peer_), (update->flags_ & telegram_api::updateDialogUnreadMark::UNREAD_MASK) != 0); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_filters(); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_filters(); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_dialog_filters(); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->config_manager(), &ConfigManager::on_dc_options_update, DcOptions(update->dc_options_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->inline_queries_manager_->on_new_query(update->query_id_, UserId(update->user_id_), Location(update->geo_), std::move(update->peer_type_), update->query_, update->offset_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->inline_queries_manager_->on_chosen_result(UserId(update->user_id_), Location(update->geo_), update->query_, update->id_, std::move(update->msg_id_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->callback_queries_manager_->on_new_query(update->flags_, update->query_id_, UserId(update->user_id_), DialogId(update->peer_), MessageId(ServerMessageId(update->msg_id_)), std::move(update->data_), update->chat_instance_, std::move(update->game_short_name_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->callback_queries_manager_->on_new_inline_query(update->flags_, update->query_id_, UserId(update->user_id_), std::move(update->msg_id_), std::move(update->data_), update->chat_instance_, std::move(update->game_short_name_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->stickers_manager_->reload_favorite_stickers(true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->animations_manager_->reload_saved_animations(true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(td_->config_manager_, &ConfigManager::request_config); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { set_pts(std::numeric_limits::max(), "updatePtsChanged").set_value(Unit()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(td_->secret_chats_manager_, &SecretChatsManager::on_update_chat, std::move(update)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { if (force_apply) { - return process_qts_update(std::move(update), 0); + return process_qts_update(std::move(update), 0, std::move(promise)); } auto qts = update->qts_; - add_pending_qts_update(std::move(update), qts); + add_pending_qts_update(std::move(update), qts, std::move(promise)); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->read_secret_chat_outbox(SecretChatId(update->chat_id_), update->max_date_, update->date_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(td_->privacy_manager_, &PrivacyManager::update_privacy, std::move(update)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->stickers_manager_->on_get_messages_sticker_set(StickerSetId(), std::move(update->stickerset_), true, "updateNewStickerSet"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->stickers_manager_->on_update_sticker_sets(); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { bool is_masks = (update->flags_ & telegram_api::updateStickerSetsOrder::MASKS_MASK) != 0; td_->stickers_manager_->on_update_sticker_sets_order(is_masks, StickersManager::convert_sticker_set_ids(update->order_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->stickers_manager_->reload_featured_sticker_sets(true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->stickers_manager_->reload_recent_stickers(false, true); td_->stickers_manager_->reload_recent_stickers(true, true); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { UserId user_id(update->user_id_); if (!user_id.is_valid()) { LOG(ERROR) << "Receive shipping query from invalid " << user_id; - return; - } - CHECK(update->shipping_address_ != nullptr); + } else { + CHECK(update->shipping_address_ != nullptr); - send_closure(G()->td(), &Td::send_update, - make_tl_object( - update->query_id_, td_->contacts_manager_->get_user_id_object(user_id, "updateNewShippingQuery"), - update->payload_.as_slice().str(), - get_address_object(get_address(std::move(update->shipping_address_))))); // TODO use convert_address + send_closure( + G()->td(), &Td::send_update, + make_tl_object( + update->query_id_, td_->contacts_manager_->get_user_id_object(user_id, "updateNewShippingQuery"), + update->payload_.as_slice().str(), + get_address_object(get_address(std::move(update->shipping_address_))))); // TODO use convert_address + } + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { UserId user_id(update->user_id_); if (!user_id.is_valid()) { LOG(ERROR) << "Receive pre-checkout query from invalid " << user_id; - return; + } else { + send_closure( + G()->td(), &Td::send_update, + make_tl_object( + update->query_id_, td_->contacts_manager_->get_user_id_object(user_id, "updateNewPreCheckoutQuery"), + update->currency_, update->total_amount_, update->payload_.as_slice().str(), update->shipping_option_id_, + get_order_info_object(get_order_info(std::move(update->info_))))); } - - send_closure(G()->td(), &Td::send_update, - make_tl_object( - update->query_id_, td_->contacts_manager_->get_user_id_object(user_id, "updateNewPreCheckoutQuery"), - update->currency_, update->total_amount_, update->payload_.as_slice().str(), - update->shipping_option_id_, get_order_info_object(get_order_info(std::move(update->info_))))); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->td(), &Td::send_update, make_tl_object(update->data_->data_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->td(), &Td::send_update, make_tl_object(update->query_id_, update->data_->data_, update->timeout_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->call_manager(), &CallManager::update_call, std::move(update)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->call_manager(), &CallManager::update_call_signaling_data, update->phone_call_id_, update->data_.as_slice().str()); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { DialogId dialog_id(ChatId(update->chat_id_)); if (!td_->messages_manager_->have_dialog_force(dialog_id)) { dialog_id = DialogId(ChannelId(update->chat_id_)); @@ -2160,70 +2345,93 @@ void UpdatesManager::on_update(tl_object_ptr upda } } send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call, std::move(update->call_), dialog_id); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call_participants, InputGroupCallId(update->call_), std::move(update->participants_), update->version_); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->contacts_manager_->on_update_contacts_reset(); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->language_pack_manager(), &LanguagePackManager::on_language_pack_too_long, std::move(update->lang_code_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { send_closure(G()->language_pack_manager(), &LanguagePackManager::on_update_language_pack, std::move(update->difference_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_update_live_location_viewed( {DialogId(update->peer_), MessageId(ServerMessageId(update->msg_id_))}); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->poll_manager_->on_get_poll(PollId(update->poll_id_), std::move(update->poll_), std::move(update->results_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->poll_manager_->on_get_poll_vote(PollId(update->poll_id_), UserId(update->user_id_), std::move(update->options_)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { td_->messages_manager_->on_get_message(std::move(update->message_), true, false, true, true, true, "updateNewScheduledMessage"); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, - bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { vector message_ids = transform(update->messages_, [](int32 scheduled_server_message_id) { return ScheduledServerMessageId(scheduled_server_message_id); }); td_->messages_manager_->on_update_delete_scheduled_messages(DialogId(update->peer_), std::move(message_ids)); + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { LOG(INFO) << "Ignore updateLoginToken after authorization"; + promise.set_value(Unit()); } -void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { +void UpdatesManager::on_update(tl_object_ptr update, bool force_apply, + Promise &&promise) { if (force_apply) { - return process_qts_update(std::move(update), 0); + return process_qts_update(std::move(update), 0, std::move(promise)); } auto qts = update->qts_; - add_pending_qts_update(std::move(update), qts); + add_pending_qts_update(std::move(update), qts, std::move(promise)); } // unsupported updates -void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { +void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise) { + promise.set_value(Unit()); } } // namespace td diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 05fd0782a..6ed66e9c5 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -34,7 +34,7 @@ class UpdatesManager : public Actor { public: UpdatesManager(Td *td, ActorShared<> parent); - void on_get_updates(tl_object_ptr &&updates_ptr); + void on_get_updates(tl_object_ptr &&updates_ptr, Promise &&promise); void on_get_updates_state(tl_object_ptr &&state, const char *source); @@ -92,12 +92,20 @@ class UpdatesManager : public Actor { int32 seq_end; int32 date; vector> updates; + Promise promise; - PendingUpdates(int32 seq_begin, int32 seq_end, int32 date, vector> &&updates) - : seq_begin(seq_begin), seq_end(seq_end), date(date), updates(std::move(updates)) { + PendingUpdates(int32 seq_begin, int32 seq_end, int32 date, vector> &&updates, + Promise &&promise) + : seq_begin(seq_begin), seq_end(seq_end), date(date), updates(std::move(updates)), promise(std::move(promise)) { } }; + class PendingQtsUpdate { + public: + tl_object_ptr update; + Promise promise; + }; + Td *td_; ActorShared<> parent_; @@ -112,7 +120,7 @@ class UpdatesManager : public Actor { std::multimap postponed_updates_; // updates received during getDifference std::multimap pending_seq_updates_; // updates with too big seq - std::map> pending_qts_updates_; // updates with too big qts + std::map pending_qts_updates_; // updates with too big qts Timeout seq_gap_timeout_; @@ -142,18 +150,21 @@ class UpdatesManager : public Actor { vector> &&new_encrypted_messages, vector> &&other_updates); - void on_pending_update(tl_object_ptr update, int32 seq, const char *source); + void on_pending_update(tl_object_ptr update, int32 seq, Promise &&promise, + const char *source); - void add_pending_qts_update(tl_object_ptr &&update, int32 qts); + void add_pending_qts_update(tl_object_ptr &&update, int32 qts, Promise &&promise); void on_pending_updates(vector> &&updates, int32 seq_begin, int32 seq_end, - int32 date, const char *source); + int32 date, Promise &&promise, const char *source); - void process_updates(vector> &&updates, bool force_apply); + void process_updates(vector> &&updates, bool force_apply, + Promise &&promise); - void process_seq_updates(int32 seq_end, int32 date, vector> &&updates); + void process_seq_updates(int32 seq_end, int32 date, vector> &&updates, + Promise &&promise); - void process_qts_update(tl_object_ptr &&update_ptr, int32 qts); + void process_qts_update(tl_object_ptr &&update_ptr, int32 qts, Promise &&promise); void process_pending_seq_updates(); @@ -199,133 +210,185 @@ class UpdatesManager : public Actor { bool is_acceptable_update(const telegram_api::Update *update) const; - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, + Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool force_apply); + void on_update(tl_object_ptr update, bool force_apply, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool force_apply, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool force_apply); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool force_apply, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, + Promise &&promise); // unsupported updates - void on_update(tl_object_ptr update, bool /*force_apply*/); + void on_update(tl_object_ptr update, bool /*force_apply*/, Promise &&promise); }; } // namespace td