diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 10881b70f..958fb1afe 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4554,6 +4554,9 @@ getGroupCall group_call_id:int32 = GroupCall; //@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls. Use null to cancel previous joinGroupCall request @source Caller synchronization source identifier; received from tgcalls @is_muted True, if the user's microphone is muted joinGroupCall group_call_id:int32 payload:groupCallPayload source:int32 is_muted:Bool = GroupCallJoinResponse; +//@description Sets group call title. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier @title New group call title; 1-128 characters +setGroupCallTitle group_call_id:int32 title:string = Ok; + //@description Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.can_change_mute_new_participants group call flag //@group_call_id Group call identifier @mute_new_participants New value of the mute_new_participants setting toggleGroupCallMuteNewParticipants group_call_id:int32 mute_new_participants:Bool = Ok; diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index ef79e650b..4c2fbb0af 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -227,6 +227,38 @@ class JoinGroupCallQuery : public Td::ResultHandler { } }; +class EditGroupCallTitleQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit EditGroupCallTitleQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(InputGroupCallId input_group_call_id, const string &title) { + send_query(G()->net_query_creator().create( + telegram_api::phone_editGroupCallTitle(input_group_call_id.get_input_group_call(), title))); + } + + 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 EditGroupCallTitleQuery: " << to_string(ptr); + td->updates_manager_->on_get_updates(std::move(ptr), std::move(promise_)); + } + + void on_error(uint64 id, Status status) override { + if (status.message() == "GROUPCALL_NOT_MODIFIED") { + promise_.set_value(Unit()); + return; + } + promise_.set_error(std::move(status)); + } +}; + class ToggleGroupCallSettingsQuery : public Td::ResultHandler { Promise promise_; @@ -440,6 +472,7 @@ struct GroupCallManager::GroupCall { bool have_pending_mute_new_participants = false; bool pending_mute_new_participants = false; + string pending_title; }; struct GroupCallManager::GroupCallParticipants { @@ -867,7 +900,13 @@ void GroupCallManager::finish_check_group_call_is_joined(InputGroupCallId input_ check_group_call_is_joined_timeout_.set_timeout_in(group_call->group_call_id.get(), next_timeout); } +const string &GroupCallManager::get_group_call_title(const GroupCall *group_call) { + CHECK(group_call != nullptr); + return group_call->pending_title.empty() ? group_call->title : group_call->pending_title; +} + bool GroupCallManager::get_group_call_mute_new_participants(const GroupCall *group_call) { + CHECK(group_call != nullptr); return group_call->have_pending_mute_new_participants ? group_call->pending_mute_new_participants : group_call->mute_new_participants; } @@ -1793,6 +1832,63 @@ void GroupCallManager::process_group_call_after_join_requests(InputGroupCallId i } } +void GroupCallManager::set_group_call_title(GroupCallId group_call_id, string title, Promise &&promise) { + TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); + + auto *group_call = get_group_call(input_group_call_id); + if (group_call == nullptr || !group_call->is_inited || !group_call->is_active || !group_call->can_be_managed) { + return promise.set_error(Status::Error(400, "Can't change group call title")); + } + + if (title == get_group_call_title(group_call)) { + return promise.set_value(Unit()); + } + + // there is no reason to save promise; we will send an update with actual value anyway + + if (group_call->pending_title.empty()) { + send_edit_group_call_title_query(input_group_call_id, title); + } + group_call->pending_title = std::move(title); + send_update_group_call(group_call, "set_group_call_title"); + promise.set_value(Unit()); +} + +void GroupCallManager::send_edit_group_call_title_query(InputGroupCallId input_group_call_id, const string &title) { + auto promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, title](Result result) { + send_closure(actor_id, &GroupCallManager::on_edit_group_call_title, input_group_call_id, title, std::move(result)); + }); + td_->create_handler(std::move(promise))->send(input_group_call_id, title); +} + +void GroupCallManager::on_edit_group_call_title(InputGroupCallId input_group_call_id, const string &title, + Result &&result) { + if (G()->close_flag()) { + return; + } + + auto *group_call = get_group_call(input_group_call_id); + if (group_call == nullptr || !group_call->is_inited || !group_call->is_active) { + return; + } + + if (group_call->pending_title != title && group_call->can_be_managed) { + // need to send another request + send_edit_group_call_title_query(input_group_call_id, group_call->pending_title); + return; + } + + bool is_different = group_call->pending_title != group_call->title; + if (is_different && group_call->can_be_managed) { + LOG(ERROR) << "Failed to set title to " << group_call->pending_title << " in " << input_group_call_id << ": " + << result.error(); + } + group_call->pending_title.clear(); + if (is_different) { + send_update_group_call(group_call, "on_set_group_call_title failed"); + } +} + void GroupCallManager::toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants, Promise &&promise) { TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); @@ -1837,18 +1933,17 @@ void GroupCallManager::on_toggle_group_call_mute_new_participants(InputGroupCall } 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 || !group_call->is_inited || !group_call->is_active || + !group_call->have_pending_mute_new_participants) { return; } - CHECK(group_call->have_pending_mute_new_participants); if (result.is_error()) { group_call->have_pending_mute_new_participants = false; if (group_call->can_be_managed && group_call->allowed_change_mute_new_participants) { LOG(ERROR) << "Failed to set mute_new_participants to " << mute_new_participants << " in " << input_group_call_id << ": " << result.error(); } - group_call->have_pending_mute_new_participants = false; if (group_call->pending_mute_new_participants != group_call->mute_new_participants) { send_update_group_call(group_call, "on_toggle_group_call_mute_new_participants failed"); } @@ -2412,8 +2507,11 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptrtitle && call.version >= group_call->version) { + string old_group_call_title = get_group_call_title(group_call); group_call->title = std::move(call.title); - need_update = true; + if (old_group_call_title != get_group_call_title(group_call)) { + need_update = true; + } } if (call.can_be_managed != group_call->can_be_managed) { group_call->can_be_managed = call.can_be_managed; @@ -2709,9 +2807,10 @@ tl_object_ptr GroupCallManager::get_group_call_object( bool can_change_mute_new_participants = group_call->is_active && group_call->can_be_managed && group_call->allowed_change_mute_new_participants; return td_api::make_object( - group_call->group_call_id.get(), group_call->title, group_call->is_active, is_joined, group_call->need_rejoin, - can_self_unmute, group_call->can_be_managed, group_call->participant_count, group_call->loaded_all_participants, - std::move(recent_speakers), mute_new_participants, can_change_mute_new_participants, group_call->duration); + group_call->group_call_id.get(), get_group_call_title(group_call), group_call->is_active, is_joined, + group_call->need_rejoin, can_self_unmute, group_call->can_be_managed, group_call->participant_count, + group_call->loaded_all_participants, std::move(recent_speakers), mute_new_participants, + can_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 316b1cbab..a44b51fc5 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -52,6 +52,8 @@ class GroupCallManager : public Actor { int32 audio_source, bool is_muted, Promise> &&promise); + void set_group_call_title(GroupCallId group_call_id, string title, Promise &&promise); + void toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants, Promise &&promise); @@ -135,6 +137,8 @@ class GroupCallManager : public Actor { void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 audio_source, Result &&result); + static const string &get_group_call_title(const GroupCall *group_call); + static bool get_group_call_mute_new_participants(const GroupCall *group_call); bool need_group_call_participants(InputGroupCallId input_group_call_id) const; @@ -180,6 +184,10 @@ class GroupCallManager : public Actor { static GroupCallParticipant *get_group_call_participant(GroupCallParticipants *group_call_participants, UserId user_id); + void send_edit_group_call_title_query(InputGroupCallId input_group_call_id, const string &title); + + void on_edit_group_call_title(InputGroupCallId input_group_call_id, const string &title, Result &&result); + void send_toggle_group_call_mute_new_participants_query(InputGroupCallId input_group_call_id, bool mute_new_participants); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 201cad534..7545cf83b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5989,6 +5989,14 @@ void Td::on_request(uint64 id, td_api::joinGroupCall &request) { request.source_, request.is_muted_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::setGroupCallTitle &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.title_); + CREATE_OK_REQUEST_PROMISE(); + group_call_manager_->set_group_call_title(GroupCallId(request.group_call_id_), std::move(request.title_), + std::move(promise)); +} + void Td::on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 829ece5f5..c60301b92 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -705,6 +705,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::joinGroupCall &request); + void on_request(uint64 id, td_api::setGroupCallTitle &request); + void on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request); void on_request(uint64 id, const td_api::inviteGroupCallParticipants &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e5ca054b2..9bf52e084 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2679,6 +2679,11 @@ class CliClient final : public Actor { true)); } else if (op == "jgcc") { send_request(td_api::make_object(as_group_call_id(args), nullptr, 0, true)); + } else if (op == "sgct") { + string chat_id; + string title; + get_args(args, chat_id, title); + send_request(td_api::make_object(as_group_call_id(chat_id), title)); } else if (op == "tgcmnp" || op == "tgcmnpe") { send_request( td_api::make_object(as_group_call_id(args), op == "tgcmnpe"));