diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2ad898fe0..09c6b1440 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4330,7 +4330,10 @@ sendCallDebugInformation call_id:int32 debug_information:string = Ok; //@description Creates a voice chat (a group call bound to a chat). Available only for supergroups; requires can_manage_calls rights @chat_id Chat identifier createVoiceChat chat_id:int53 = GroupCallId; -//@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls @source Caller source identifier, received from tgcalls @is_muted True, if the user's microphone is muted +//@description Returns information about a group call @group_call_id Group call identifier +getGroupCall group_call_id:string = GroupCall; + +//@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls @source Caller synchronization source identifier; received from tgcalls @is_muted True, if the user's microphone is muted joinGroupCall group_call_id:string payload:groupCallPayload source:int32 is_muted:Bool = GroupCallJoinResponse; //@description Toggles whether new members of a group call can be unmuted only by administrators of the group call. Requires can_manage_calls rights in the corresponding chat and allowed_change_mute_mew_members group call flag @@ -4345,10 +4348,10 @@ inviteGroupCallMembers group_call_id:string user_ids:vector = Ok; //@group_call_id Group call identifier @user_id User identifier @is_muted Pass true if the user must be muted and false otherwise toggleGroupCallMemberIsMuted group_call_id:string user_id:int32 is_muted:Bool = Ok; -//@description Checks group call source for validness. If the method returns an error with a message "GROUP_CALL_JOIN_MISSING", the call needs to be rejoined @group_call_id Group call identifier @source Caller source identifier +//@description Checks group call source for validness. If the method returns an error with a message "GROUP_CALL_JOIN_MISSING", the call needs to be rejoined @group_call_id Group call identifier @source Caller synchronization source identifier checkGroupCallSource group_call_id:string source:int32 = Ok; -//@description Leaves a group call @group_call_id Group call identifier @source Caller source identifier +//@description Leaves a group call @group_call_id Group call identifier @source Caller synchronization source identifier leaveGroupCall group_call_id:string source:int32 = Ok; //@description Discards a group call. Requires can_manage_calls rights in the corresponding chat @group_call_id Group call identifier diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index eda2e8e3c..ed99cd3d5 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index bce42d1e1..9087d8f23 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -63,6 +63,38 @@ class CreateGroupCallQuery : public Td::ResultHandler { } }; +class GetGroupCallQuery : public Td::ResultHandler { + Promise> promise_; + InputGroupCallId group_call_id_; + + public: + explicit GetGroupCallQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(InputGroupCallId group_call_id) { + group_call_id_ = group_call_id; + + send_query(G()->net_query_creator().create(telegram_api::phone_getGroupCall(group_call_id.get_input_group_call()))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetGroupCallQuery: " << to_string(ptr); + + promise_.set_value(std::move(ptr)); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + class JoinGroupCallQuery : public Td::ResultHandler { Promise promise_; InputGroupCallId group_call_id_; @@ -327,6 +359,79 @@ void GroupCallManager::create_voice_chat(ChannelId channel_id, Promisecreate_handler(std::move(promise))->send(channel_id); } +const GroupCallManager::GroupCall *GroupCallManager::get_group_call(InputGroupCallId group_call_id) const { + auto it = group_calls_.find(group_call_id); + if (it == group_calls_.end()) { + return nullptr; + } else { + return it->second.get(); + } +} + +GroupCallManager::GroupCall *GroupCallManager::get_group_call(InputGroupCallId group_call_id) { + auto it = group_calls_.find(group_call_id); + if (it == group_calls_.end()) { + return nullptr; + } else { + return it->second.get(); + } +} + +void GroupCallManager::get_group_call(InputGroupCallId group_call_id, + Promise> &&promise) { + auto group_call = get_group_call(group_call_id); + if (group_call != nullptr) { + return promise.set_value(get_group_call_object(group_call_id, group_call)); + } + + reload_group_call(group_call_id, std::move(promise)); +} + +void GroupCallManager::reload_group_call(InputGroupCallId group_call_id, + Promise> &&promise) { + auto &queries = load_group_call_queries_[group_call_id]; + queries.push_back(std::move(promise)); + if (queries.size() == 1) { + auto query_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), group_call_id](Result> &&result) { + send_closure(actor_id, &GroupCallManager::finish_get_group_call, group_call_id, std::move(result)); + }); + td_->create_handler(std::move(query_promise))->send(group_call_id); + } +} + +void GroupCallManager::finish_get_group_call(InputGroupCallId group_call_id, + Result> &&result) { + auto it = load_group_call_queries_.find(group_call_id); + CHECK(it != load_group_call_queries_.end()); + CHECK(!it->second.empty()); + auto promises = std::move(it->second); + load_group_call_queries_.erase(it); + + if (result.is_ok()) { + td_->contacts_manager_->on_get_users(std::move(result.ok_ref()->users_), "finish_get_group_call"); + + auto call_id = update_group_call(result.ok()->call_); + if (call_id != group_call_id) { + LOG(ERROR) << "Expected " << group_call_id << ", but received " << to_string(result.ok()); + result = Status::Error(500, "Receive another group call"); + } + } + + if (result.is_error()) { + for (auto &promise : promises) { + promise.set_error(result.error().clone()); + } + return; + } + + auto group_call = get_group_call(group_call_id); + CHECK(group_call != nullptr); + for (auto &promise : promises) { + promise.set_value(get_group_call_object(group_call_id, group_call)); + } +} + void GroupCallManager::join_group_call(InputGroupCallId group_call_id, td_api::object_ptr &&payload, int32 source, bool is_muted, diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index 57c93fc54..18c24b562 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -32,6 +32,8 @@ class GroupCallManager : public Actor { void create_voice_chat(ChannelId channel_id, Promise &&promise); + void get_group_call(InputGroupCallId group_call_id, Promise> &&promise); + void join_group_call(InputGroupCallId group_call_id, td_api::object_ptr &&payload, int32 source, bool is_muted, Promise> &&promise); @@ -61,6 +63,14 @@ class GroupCallManager : public Actor { void tear_down() override; + const GroupCall *get_group_call(InputGroupCallId group_call_id) const; + GroupCall *get_group_call(InputGroupCallId group_call_id); + + void reload_group_call(InputGroupCallId group_call_id, Promise> &&promise); + + void finish_get_group_call(InputGroupCallId group_call_id, + Result> &&result); + void on_join_group_call_response(InputGroupCallId group_call_id, string json_response); void finish_join_group_call(InputGroupCallId group_call_id, uint64 generation, Status error); @@ -81,6 +91,9 @@ class GroupCallManager : public Actor { std::unordered_map, InputGroupCallIdHash> group_calls_; + std::unordered_map>>, InputGroupCallIdHash> + load_group_call_queries_; + std::unordered_map, InputGroupCallIdHash> pending_join_requests_; uint64 join_group_request_generation_ = 0; }; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index fd02c3702..84fd71d59 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6041,6 +6041,14 @@ void Td::on_request(uint64 id, const td_api::createVoiceChat &request) { contacts_manager_->create_channel_voice_chat(DialogId(request.chat_id_), std::move(query_promise)); } +void Td::on_request(uint64 id, const td_api::getGroupCall &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + TRY_RESULT_PROMISE(promise, group_call_id, InputGroupCallId::from_group_call_id(request.group_call_id_)); + + group_call_manager_->get_group_call(group_call_id, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::joinGroupCall &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index a77af2734..b675bd536 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -694,6 +694,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::createVoiceChat &request); + void on_request(uint64 id, const td_api::getGroupCall &request); + void on_request(uint64 id, td_api::joinGroupCall &request); void on_request(uint64 id, const td_api::toggleGroupCallMuteNewMembers &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4c5446eaa..894bc0553 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2840,6 +2840,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_call_id(args), "{}")); } else if (op == "cvc") { send_request(td_api::make_object(as_chat_id(args))); + } else if (op == "ggc") { + send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "jgc") { vector> fingerprints; fingerprints.push_back(td_api::make_object("hash", "setup", "fingerprint"));