From c4d8f301a1ba51797f924e7f78373beff935fa8c Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 17 Dec 2020 02:07:05 +0300 Subject: [PATCH] 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; };