From e5bf347ceb17ed0210e945d78e7e6dcf769abf48 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 26 Nov 2020 11:21:26 +0300 Subject: [PATCH 1/5] Add discardGroupCall. --- td/generate/scheme/td_api.tl | 3 +++ td/generate/scheme/td_api.tlo | Bin 186312 -> 186412 bytes td/telegram/Td.cpp | 8 ++++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 5 files changed, 15 insertions(+) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 648287590..66f02bd6f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4293,6 +4293,9 @@ sendCallDebugInformation call_id:int32 debug_information:string = Ok; //@description Creates a group call in a chat. Available only for supergroups; requires can_manage_calls rights @chat_id Chat identifier createChatGroupCall chat_id:int53 = GroupCallId; +//@description Discards a group call. Requires can_manage_calls rights in the corresponding chat @group_call_id Group call identifier +discardGroupCall group_call_id:string = Ok; + //@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked toggleMessageSenderIsBlocked sender:MessageSender is_blocked:Bool = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 718af5e8b7a84b603e35a4bba0d4a038f5b7d4a9..94bcc3fca4081be48cfe4056597a0ee9dcedb548 100644 GIT binary patch delta 64 zcmV-G0KfmpuM4cO3xI?Hv;veA0f@Ji6asT473&#=uMlKub7Nt0WJhvub#OyrY;2d2 Wt^yO6$Q=PBmp~o@7`F&I0>GUf{uhG) delta 27 jcmZ3pf&0XI?uHh|Elg8H7~8i`6=5n?-JWB`bYLz3nSct5 diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index d61fd3ca9..90a30dbfe 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6041,6 +6041,14 @@ void Td::on_request(uint64 id, const td_api::createChatGroupCall &request) { contacts_manager_->create_channel_group_call(DialogId(request.chat_id_), std::move(query_promise)); } +void Td::on_request(uint64 id, const td_api::discardGroupCall &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + TRY_RESULT_PROMISE(promise, group_call_id, InputGroupCallId::from_group_call_id(request.group_call_id_)); + + group_call_manager_->discard_group_call(group_call_id, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request) { CHECK_IS_USER(); CREATE_REQUEST(UpgradeGroupChatToSupergroupChatRequest, request.chat_id_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b2dffcd9a..8fe4a828a 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::createChatGroupCall &request); + void on_request(uint64 id, const td_api::discardGroupCall &request); + void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request); void on_request(uint64 id, const td_api::getChatListsToAddChat &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 56d7bb13b..40c712856 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2836,6 +2836,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_call_id(args), "{}")); } else if (op == "ccgc") { send_request(td_api::make_object(as_chat_id(args))); + } else if (op == "dgc") { + send_request(td_api::make_object(args)); } else if (op == "gcil") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "ccil") { From 5cfda1df72a0342d0ab24fb620658f7f160fe83e Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 26 Nov 2020 11:37:54 +0300 Subject: [PATCH 2/5] Add leaveGroupCall method. --- td/generate/scheme/td_api.tl | 3 +++ td/generate/scheme/td_api.tlo | Bin 186412 -> 186540 bytes td/telegram/InputGroupCallId.cpp | 2 +- td/telegram/Td.cpp | 8 ++++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 2 ++ 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 66f02bd6f..c9a98eda4 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4293,6 +4293,9 @@ sendCallDebugInformation call_id:int32 debug_information:string = Ok; //@description Creates a group call in a chat. Available only for supergroups; requires can_manage_calls rights @chat_id Chat identifier createChatGroupCall chat_id:int53 = GroupCallId; +//@description Leaves a group call @group_call_id Group call identifier @source Caller 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 discardGroupCall group_call_id:string = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 94bcc3fca4081be48cfe4056597a0ee9dcedb548..f9208e19c09002e91dd9070155f867db801b9c95 100644 GIT binary patch delta 66 zcmV-I0KNaLunVlQ3xI?Hv;veA0g1Pj6ap7+7%_Em5e{r+VRmIla&L8TLt$)e0BOGM Y)R(*+0W_0*h7gzdA_640tbzi7RXC#=O#lD@ delta 27 jcmZ3pk$cSs?uHh|Elg8H7(2F46=4$3+pg2h)DQ{)m01bk diff --git a/td/telegram/InputGroupCallId.cpp b/td/telegram/InputGroupCallId.cpp index 296dc3d89..74c2f04d4 100644 --- a/td/telegram/InputGroupCallId.cpp +++ b/td/telegram/InputGroupCallId.cpp @@ -24,7 +24,7 @@ Result InputGroupCallId::from_group_call_id(const string &grou auto r_group_call_id = to_integer_safe(splitted.first); auto r_access_hash = to_integer_safe(splitted.second); if (r_group_call_id.is_error() || r_access_hash.is_error()) { - return Status::Error("Invalid group call identifier specified"); + return Status::Error(400, "Invalid group call identifier specified"); } return InputGroupCallId{r_group_call_id.ok(), r_access_hash.ok()}; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 90a30dbfe..44a8b5896 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6041,6 +6041,14 @@ void Td::on_request(uint64 id, const td_api::createChatGroupCall &request) { contacts_manager_->create_channel_group_call(DialogId(request.chat_id_), std::move(query_promise)); } +void Td::on_request(uint64 id, const td_api::leaveGroupCall &request) { + CHECK_IS_USER(); + CREATE_OK_REQUEST_PROMISE(); + TRY_RESULT_PROMISE(promise, group_call_id, InputGroupCallId::from_group_call_id(request.group_call_id_)); + + group_call_manager_->leave_group_call(group_call_id, request.source_, std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::discardGroupCall &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 8fe4a828a..6107c8ce1 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::createChatGroupCall &request); + void on_request(uint64 id, const td_api::leaveGroupCall &request); + void on_request(uint64 id, const td_api::discardGroupCall &request); void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 40c712856..370ab3e32 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2836,6 +2836,8 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_call_id(args), "{}")); } else if (op == "ccgc") { send_request(td_api::make_object(as_chat_id(args))); + } else if (op == "lgc") { + send_request(td_api::make_object(args, 123)); } else if (op == "dgc") { send_request(td_api::make_object(args)); } else if (op == "gcil") { From 2f1b857b7e7cd299afc2f975ab2bdb2807375764 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 26 Nov 2020 13:44:48 +0300 Subject: [PATCH 3/5] Disallow empty group call identifier in requests. --- td/telegram/InputGroupCallId.cpp | 5 ++++- td/telegram/InputGroupCallId.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/td/telegram/InputGroupCallId.cpp b/td/telegram/InputGroupCallId.cpp index 74c2f04d4..1bc29c7d0 100644 --- a/td/telegram/InputGroupCallId.cpp +++ b/td/telegram/InputGroupCallId.cpp @@ -15,8 +15,11 @@ InputGroupCallId::InputGroupCallId(const tl_object_ptrid_), access_hash(input_group_call->access_hash_) { } -Result InputGroupCallId::from_group_call_id(const string &group_call_id) { +Result InputGroupCallId::from_group_call_id(const string &group_call_id, bool allow_empty) { if (group_call_id.empty()) { + if (!allow_empty) { + return Status::Error(400, "Empty group call identifier specified"); + } return InputGroupCallId(); } diff --git a/td/telegram/InputGroupCallId.h b/td/telegram/InputGroupCallId.h index b8583e1e6..e8f1d1313 100644 --- a/td/telegram/InputGroupCallId.h +++ b/td/telegram/InputGroupCallId.h @@ -28,7 +28,7 @@ class InputGroupCallId { InputGroupCallId(int64 group_call_id, int64 access_hash) : group_call_id(group_call_id), access_hash(access_hash) { } - static Result from_group_call_id(const string &group_call_id); + static Result from_group_call_id(const string &group_call_id, bool allow_empty = false); string get_group_call_id() const; From 32295e2b6e09573089de1f378fb2bfe93eb9036d Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 26 Nov 2020 13:47:20 +0300 Subject: [PATCH 4/5] Add missing files. --- td/telegram/GroupCallManager.cpp | 227 +++++++++++++++++++++++++++++++ td/telegram/GroupCallManager.h | 54 ++++++++ 2 files changed, 281 insertions(+) create mode 100644 td/telegram/GroupCallManager.cpp create mode 100644 td/telegram/GroupCallManager.h diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp new file mode 100644 index 000000000..b002e7d04 --- /dev/null +++ b/td/telegram/GroupCallManager.cpp @@ -0,0 +1,227 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/GroupCallManager.h" + +#include "td/telegram/ContactsManager.h" +#include "td/telegram/Global.h" +#include "td/telegram/Td.h" +#include "td/telegram/UpdatesManager.h" + +#include "td/utils/Random.h" + +namespace td { + +class CreateGroupCallQuery : public Td::ResultHandler { + Promise promise_; + ChannelId channel_id_; + + public: + explicit CreateGroupCallQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(ChannelId channel_id) { + channel_id_ = channel_id; + + auto input_channel = td->contacts_manager_->get_input_channel(channel_id); + CHECK(input_channel != nullptr); + + send_query(G()->net_query_creator().create( + telegram_api::phone_createGroupCall(std::move(input_channel), Random::secure_int32()))); + } + + 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 CreateGroupCallQuery: " << to_string(ptr); + + auto group_call_ids = td->updates_manager_->get_update_new_group_call_ids(ptr.get()); + if (group_call_ids.size() != 1) { + LOG(ERROR) << "Receive wrong CreateGroupCallQuery response " << to_string(ptr); + return on_error(id, Status::Error(500, "Receive wrong response")); + } + + 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])); + } + + void on_error(uint64 id, Status status) override { + td->contacts_manager_->on_get_channel_error(channel_id_, status, "CreateGroupCallQuery"); + promise_.set_error(std::move(status)); + } +}; + +class LeaveGroupCallQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit LeaveGroupCallQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(InputGroupCallId group_call_id, int32 source) { + send_query(G()->net_query_creator().create( + telegram_api::phone_leaveGroupCall(group_call_id.get_input_group_call(), source))); + } + + 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 LeaveGroupCallQuery: " << to_string(ptr); + td->updates_manager_->on_get_updates(std::move(ptr)); + + // TODO set promise after updates are processed + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + +class DiscardGroupCallQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit DiscardGroupCallQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(InputGroupCallId group_call_id) { + send_query( + G()->net_query_creator().create(telegram_api::phone_discardGroupCall(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 DiscardGroupCallQuery: " << to_string(ptr); + td->updates_manager_->on_get_updates(std::move(ptr)); + + // TODO set promise after updates are processed + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + +struct GroupCallManager::GroupCall { + bool is_active = false; + int32 member_count = 0; + int32 version = -1; + int32 duration = 0; +}; + +GroupCallManager::GroupCallManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { +} + +void GroupCallManager::tear_down() { + parent_.reset(); +} + +void GroupCallManager::create_group_call(ChannelId channel_id, Promise &&promise) { + td_->create_handler(std::move(promise))->send(channel_id); +} + +void GroupCallManager::leave_group_call(InputGroupCallId group_call_id, int32 source, Promise &&promise) { + td_->create_handler(std::move(promise))->send(group_call_id, source); +} + +void GroupCallManager::discard_group_call(InputGroupCallId group_call_id, Promise &&promise) { + td_->create_handler(std::move(promise))->send(group_call_id); +} + +void GroupCallManager::on_update_group_call(tl_object_ptr group_call_ptr) { + auto call_id = update_group_call(group_call_ptr); + if (call_id.is_valid()) { + LOG(INFO) << "Update " << call_id; + } else { + LOG(ERROR) << "Receive invalid " << to_string(group_call_ptr); + } +} + +InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr &group_call_ptr) { + CHECK(group_call_ptr != nullptr); + + InputGroupCallId call_id; + GroupCall call; + switch (group_call_ptr->get_id()) { + case telegram_api::groupCall::ID: { + auto group_call = static_cast(group_call_ptr.get()); + call_id = InputGroupCallId(group_call->id_, group_call->access_hash_); + call.is_active = true; + call.member_count = group_call->participants_count_; + call.version = group_call->version_; + break; + } + case telegram_api::groupCallDiscarded::ID: { + auto group_call = static_cast(group_call_ptr.get()); + call_id = InputGroupCallId(group_call->id_, group_call->access_hash_); + call.duration = group_call->duration_; + break; + } + default: + UNREACHABLE(); + } + if (!call_id.is_valid() || call.member_count < 0) { + return {}; + } + + auto &group_call = group_calls_[call_id]; + bool need_update = false; + if (group_call == nullptr) { + group_call = make_unique(); + *group_call = std::move(call); + need_update = true; + } else { + if (!group_call->is_active) { + // never update ended calls + } else if (!call.is_active) { + // always update to an ended call + *group_call = std::move(call); + need_update = true; + } else { + if (call.version > group_call->version) { + need_update = call.member_count != group_call->member_count; + *group_call = std::move(call); + } + } + } + + if (need_update) { + send_closure(G()->td(), &Td::send_update, get_update_group_call_object(call_id, group_call.get())); + } + + return call_id; +} + +tl_object_ptr GroupCallManager::get_group_call_object(InputGroupCallId group_call_id, + const GroupCall *group_call) { + CHECK(group_call != nullptr); + return td_api::make_object(group_call_id.get_group_call_id(), group_call->is_active, + group_call->member_count, group_call->duration); +} + +tl_object_ptr GroupCallManager::get_update_group_call_object(InputGroupCallId group_call_id, + const GroupCall *group_call) { + return td_api::make_object(get_group_call_object(group_call_id, group_call)); +} + +} // namespace td diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h new file mode 100644 index 000000000..871306f99 --- /dev/null +++ b/td/telegram/GroupCallManager.h @@ -0,0 +1,54 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/ChannelId.h" +#include "td/telegram/InputGroupCallId.h" +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/actor/actor.h" +#include "td/actor/PromiseFuture.h" + +#include + +namespace td { + +class Td; + +class GroupCallManager : public Actor { + public: + GroupCallManager(Td *td, ActorShared<> parent); + + void create_group_call(ChannelId channel_id, Promise &&promise); + + void leave_group_call(InputGroupCallId group_call_id, int32 source, Promise &&promise); + + void discard_group_call(InputGroupCallId group_call_id, Promise &&promise); + + void on_update_group_call(tl_object_ptr group_call_ptr); + + private: + struct GroupCall; + + void tear_down() override; + + InputGroupCallId update_group_call(const tl_object_ptr &group_call_ptr); + + static tl_object_ptr get_update_group_call_object(InputGroupCallId group_call_id, + const GroupCall *group_call); + + static tl_object_ptr get_group_call_object(InputGroupCallId group_call_id, + const GroupCall *group_call); + + Td *td_; + ActorShared<> parent_; + + std::unordered_map, InputGroupCallIdHash> group_calls_; +}; + +} // namespace td From a2f86155a902f8609d49f477aecafec9981dba2b Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Fri, 25 Dec 2020 19:36:05 +0100 Subject: [PATCH 5/5] Replace nullptr --- td/telegram/GroupCallManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index b002e7d04..47b1c92d9 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -158,7 +158,9 @@ void GroupCallManager::on_update_group_call(tl_object_ptr &group_call_ptr) { - CHECK(group_call_ptr != nullptr); + if (group_call_ptr == nullptr) { + return {}; + } InputGroupCallId call_id; GroupCall call;