Add groupCallParticipant.can_be_muted/can_be_unmuted flags.

This commit is contained in:
levlam 2020-12-17 02:07:05 +03:00
parent bfcc7d17c4
commit c4d8f301a1
6 changed files with 102 additions and 22 deletions

View File

@ -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<groupCallJoinResponseCandidate> = 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<int32> = 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;

Binary file not shown.

View File

@ -596,7 +596,7 @@ GroupCallManager::GroupCall *GroupCallManager::get_group_call(InputGroupCallId i
}
}
Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) {
Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) const {
switch (dialog_id.get_type()) {
case DialogType::Chat: {
auto chat_id = dialog_id.get_chat_id();
@ -636,6 +636,14 @@ Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) {
return Status::OK();
}
bool GroupCallManager::can_manage_group_call(InputGroupCallId input_group_call_id) const {
auto group_call = get_group_call(input_group_call_id);
if (group_call == nullptr) {
return false;
}
return can_manage_group_calls(group_call->dialog_id).is_ok();
}
void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&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<UserId, UserIdHash> removed_user_ids(group_call_participants->administrator_user_ids.begin(),
group_call_participants->administrator_user_ids.end());
std::unordered_set<UserId, UserIdHash> 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,

View File

@ -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<GroupCallId> &&promise);
@ -131,6 +133,12 @@ class GroupCallManager : public Actor {
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&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);

View File

@ -30,6 +30,32 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::gro
is_just_joined = participant->just_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<td_api::groupCallParticipant> GroupCallParticipant::get_group_call_participant_object(
ContactsManager *contacts_manager) const {
if (!is_valid()) {
@ -37,12 +63,13 @@ td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group
}
return td_api::make_object<td_api::groupCallParticipant>(
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;
}

View File

@ -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<telegram_api::groupCallParticipant> &participant);
bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin);
int64 get_real_order() const {
return (static_cast<int64>(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<telegram_api::groupCallParticipant> &participant);
td_api::object_ptr<td_api::groupCallParticipant> get_group_call_participant_object(
ContactsManager *contacts_manager) const;
};