diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index d42fd0018..e938257a1 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4376,15 +4376,15 @@ addChatMember chat_id:int53 user_id:int32 forward_limit:int32 = Ok; addChatMembers chat_id:int53 user_ids:vector = Ok; //@description Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for adding new members to the chat and transferring chat ownership; instead, use addChatMember or transferChatOwnership -//@chat_id Chat identifier @user_id User identifier @status The new status of the member in the chat -setChatMemberStatus chat_id:int53 user_id:int32 status:ChatMemberStatus = Ok; +//@chat_id Chat identifier @member_id Member identifier. Chats can be only banned and unbanned in supergroups and channels @status The new status of the member in the chat +setChatMemberStatus chat_id:int53 member_id:MessageSender status:ChatMemberStatus = Ok; //@description Bans a member in a chat. Members can't be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first //@chat_id Chat identifier -//@user_id Identifier of the user +//@member_id Member identifier //@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Ignored in basic groups //@revoke_messages Pass true to delete all messages in the chat for the user. Always true for supergroups and channels -banChatMember chat_id:int53 user_id:int32 banned_until_date:int32 revoke_messages:Bool = Ok; +banChatMember chat_id:int53 member_id:MessageSender banned_until_date:int32 revoke_messages:Bool = Ok; //@description Checks whether the current session can be used to transfer a chat ownership to another user canTransferOwnership = CanTransferOwnershipResult; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 372667a3a..7e09f86fe 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6845,41 +6845,41 @@ void ContactsManager::add_channel_participants(ChannelId channel_id, const vecto td_->create_handler(std::move(promise))->send(channel_id, std::move(input_users)); } -void ContactsManager::change_channel_participant_status(ChannelId channel_id, UserId user_id, +void ContactsManager::change_channel_participant_status(ChannelId channel_id, DialogId participant_dialog_id, DialogParticipantStatus status, Promise &&promise) { auto c = get_channel(channel_id); if (c == nullptr) { return promise.set_error(Status::Error(6, "Chat info not found")); } - auto input_peer = get_input_peer_user(user_id, AccessRights::Read); + auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read); if (input_peer == nullptr) { - return promise.set_error(Status::Error(6, "User not found")); + return promise.set_error(Status::Error(6, "Member not found")); } - if (user_id == get_my_id()) { + if (participant_dialog_id == DialogId(get_my_id())) { // fast path is needed, because get_channel_status may return Creator, while GetChannelParticipantQuery returning Left - return change_channel_participant_status_impl(channel_id, user_id, std::move(status), get_channel_status(c), - std::move(promise)); + return change_channel_participant_status_impl(channel_id, participant_dialog_id, std::move(status), + get_channel_status(c), std::move(promise)); } auto on_result_promise = - PromiseCreator::lambda([actor_id = actor_id(this), channel_id, user_id, status, + PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id, status, promise = std::move(promise)](Result r_dialog_participant) mutable { // ResultHandlers are cleared before managers, so it is safe to capture this if (r_dialog_participant.is_error()) { return promise.set_error(r_dialog_participant.move_as_error()); } - send_closure(actor_id, &ContactsManager::change_channel_participant_status_impl, channel_id, user_id, - std::move(status), r_dialog_participant.ok().status, std::move(promise)); + send_closure(actor_id, &ContactsManager::change_channel_participant_status_impl, channel_id, + participant_dialog_id, std::move(status), r_dialog_participant.ok().status, std::move(promise)); }); td_->create_handler(std::move(on_result_promise)) - ->send(channel_id, DialogId(user_id), std::move(input_peer)); + ->send(channel_id, participant_dialog_id, std::move(input_peer)); } -void ContactsManager::change_channel_participant_status_impl(ChannelId channel_id, UserId user_id, +void ContactsManager::change_channel_participant_status_impl(ChannelId channel_id, DialogId participant_dialog_id, DialogParticipantStatus status, DialogParticipantStatus old_status, Promise &&promise) { @@ -6887,7 +6887,8 @@ void ContactsManager::change_channel_participant_status_impl(ChannelId channel_i return promise.set_value(Unit()); } - LOG(INFO) << "Change status of " << user_id << " in " << channel_id << " from " << old_status << " to " << status; + LOG(INFO) << "Change status of " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to " + << status; bool need_add = false; bool need_promote = false; bool need_restrict = false; @@ -6898,23 +6899,16 @@ void ContactsManager::change_channel_participant_status_impl(ChannelId channel_i if (!status.is_creator()) { return promise.set_error(Status::Error(3, "Can't remove chat owner")); } + if (participant_dialog_id != DialogId(get_my_id())) { + return promise.set_error(Status::Error(3, "Not enough rights to edit chat owner rights")); + } if (status.is_member() == old_status.is_member()) { // change rank and is_anonymous - if (user_id != get_my_id()) { - return promise.set_error(Status::Error(3, "Not enough rights to change chat owner rights")); - } - - auto input_user = get_input_user(user_id); - if (input_user == nullptr) { - return promise.set_error(Status::Error(3, "User not found")); - } - + auto input_user = get_input_user(get_my_id()); + CHECK(input_user != nullptr); td_->create_handler(std::move(promise))->send(channel_id, std::move(input_user), status); return; } - if (user_id != get_my_id()) { - return promise.set_error(Status::Error(3, "Not enough rights to edit chat owner membership")); - } if (status.is_member()) { // creator not member -> creator member need_add = true; @@ -6952,14 +6946,21 @@ void ContactsManager::change_channel_participant_status_impl(ChannelId channel_i } if (need_promote) { - return promote_channel_participant(channel_id, user_id, std::move(status), std::move(old_status), - std::move(promise)); + if (participant_dialog_id.get_type() != DialogType::User) { + return promise.set_error(Status::Error(400, "Can't promote chats to chat administrators")); + } + return promote_channel_participant(channel_id, participant_dialog_id.get_user_id(), std::move(status), + std::move(old_status), std::move(promise)); } else if (need_restrict) { - return restrict_channel_participant(channel_id, user_id, std::move(status), std::move(old_status), + return restrict_channel_participant(channel_id, participant_dialog_id, std::move(status), std::move(old_status), std::move(promise)); } else { CHECK(need_add); - return add_channel_participant(channel_id, user_id, std::move(promise), std::move(old_status)); + if (participant_dialog_id.get_type() != DialogType::User) { + return promise.set_error(Status::Error(400, "Can't add chats as chat members")); + } + return add_channel_participant(channel_id, participant_dialog_id.get_user_id(), std::move(promise), + std::move(old_status)); } } @@ -7383,15 +7384,17 @@ void ContactsManager::delete_chat_participant(ChatId chat_id, UserId user_id, bo td_->create_handler(std::move(promise))->send(chat_id, std::move(input_user), revoke_messages); } -void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status, - DialogParticipantStatus old_status, Promise &&promise) { - LOG(INFO) << "Restrict " << user_id << " in " << channel_id << " from " << old_status << " to " << status; +void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + DialogParticipantStatus status, DialogParticipantStatus old_status, + Promise &&promise) { + LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to " + << status; const Channel *c = get_channel(channel_id); if (c == nullptr) { return promise.set_error(Status::Error(3, "Chat info not found")); } if (!c->status.is_member() && !c->status.is_creator()) { - if (user_id == get_my_id()) { + if (participant_dialog_id == DialogId(get_my_id())) { if (status.is_member()) { return promise.set_error(Status::Error(3, "Can't unrestrict self")); } @@ -7400,12 +7403,12 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId return promise.set_error(Status::Error(3, "Not in the chat")); } } - auto input_peer = get_input_peer_user(user_id, AccessRights::Read); + auto input_peer = td_->messages_manager_->get_input_peer(participant_dialog_id, AccessRights::Read); if (input_peer == nullptr) { - return promise.set_error(Status::Error(3, "User not found")); + return promise.set_error(Status::Error(3, "Member not found")); } - if (user_id == get_my_id()) { + if (participant_dialog_id == DialogId(get_my_id())) { if (status.is_restricted() || status.is_banned()) { return promise.set_error(Status::Error(3, "Can't restrict self")); } @@ -7414,7 +7417,7 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId } // leave the channel - speculative_add_channel_user(channel_id, user_id, status, c->status); + speculative_add_channel_user(channel_id, participant_dialog_id.get_user_id(), status, c->status); td_->create_handler(std::move(promise))->send(channel_id); return; } @@ -7428,22 +7431,23 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId if (old_status.is_member() && !status.is_member() && !status.is_banned()) { // we can't make participant Left without kicking it first - auto on_result_promise = PromiseCreator::lambda([channel_id, user_id, status, + auto on_result_promise = PromiseCreator::lambda([channel_id, participant_dialog_id, status, promise = std::move(promise)](Result<> result) mutable { if (result.is_error()) { return promise.set_error(result.move_as_error()); } - create_actor( - "RestrictChannelParticipantSleepActor", 1.0, - PromiseCreator::lambda([channel_id, user_id, status, promise = std::move(promise)](Result<> result) mutable { - if (result.is_error()) { - return promise.set_error(result.move_as_error()); - } + create_actor("RestrictChannelParticipantSleepActor", 1.0, + PromiseCreator::lambda([channel_id, participant_dialog_id, status, + promise = std::move(promise)](Result<> result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } - send_closure(G()->contacts_manager(), &ContactsManager::restrict_channel_participant, channel_id, user_id, - status, DialogParticipantStatus::Banned(0), std::move(promise)); - })) + send_closure(G()->contacts_manager(), &ContactsManager::restrict_channel_participant, + channel_id, participant_dialog_id, status, + DialogParticipantStatus::Banned(0), std::move(promise)); + })) .release(); }); @@ -7451,7 +7455,9 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, UserId status = DialogParticipantStatus::Banned(0); } - speculative_add_channel_user(channel_id, user_id, status, old_status); + if (participant_dialog_id.get_type() == DialogType::User) { + speculative_add_channel_user(channel_id, participant_dialog_id.get_user_id(), status, old_status); + } td_->create_handler(std::move(promise))->send(channel_id, std::move(input_peer), status); } @@ -14513,7 +14519,7 @@ void ContactsManager::add_dialog_participants(DialogId dialog_id, const vector &chat_member_status, Promise &&promise) { auto status = get_dialog_participant_status(chat_member_status); @@ -14525,9 +14531,18 @@ void ContactsManager::set_dialog_participant_status(DialogId dialog_id, UserId u case DialogType::User: return promise.set_error(Status::Error(3, "Chat member status can't be changed in private chats")); case DialogType::Chat: - return change_chat_participant_status(dialog_id.get_chat_id(), user_id, status, std::move(promise)); + if (participant_dialog_id.get_type() != DialogType::User) { + if (status == DialogParticipantStatus::Left()) { + return promise.set_value(Unit()); + } else { + return promise.set_error(Status::Error(3, "Chats can't be members of basic groups")); + } + } + return change_chat_participant_status(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), status, + std::move(promise)); case DialogType::Channel: - return change_channel_participant_status(dialog_id.get_channel_id(), user_id, status, std::move(promise)); + return change_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id, status, + std::move(promise)); case DialogType::SecretChat: return promise.set_error(Status::Error(3, "Chat member status can't be changed in secret chats")); case DialogType::None: @@ -14536,22 +14551,26 @@ void ContactsManager::set_dialog_participant_status(DialogId dialog_id, UserId u } } -void ContactsManager::ban_dialog_participant(DialogId dialog_id, UserId user_id, int32 banned_until_date, - bool revoke_messages, Promise &&promise) { +void ContactsManager::ban_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, + int32 banned_until_date, bool revoke_messages, Promise &&promise) { if (!td_->messages_manager_->have_dialog_force(dialog_id, "ban_dialog_participant")) { return promise.set_error(Status::Error(3, "Chat not found")); } switch (dialog_id.get_type()) { case DialogType::User: - return promise.set_error(Status::Error(3, "Can't ban members in a private chat")); + return promise.set_error(Status::Error(3, "Can't ban members in private chats")); case DialogType::Chat: - return delete_chat_participant(dialog_id.get_chat_id(), user_id, revoke_messages, std::move(promise)); + if (participant_dialog_id.get_type() != DialogType::User) { + return promise.set_error(Status::Error(3, "Can't ban chats in basic groups")); + } + return delete_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), revoke_messages, + std::move(promise)); case DialogType::Channel: - return change_channel_participant_status(dialog_id.get_channel_id(), user_id, + return change_channel_participant_status(dialog_id.get_channel_id(), participant_dialog_id, DialogParticipantStatus::Banned(banned_until_date), std::move(promise)); case DialogType::SecretChat: - return promise.set_error(Status::Error(3, "Can't ban members in a secret chat")); + return promise.set_error(Status::Error(3, "Can't ban members in secret chats")); case DialogType::None: default: UNREACHABLE(); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index f48edb578..ba59d8986 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -520,12 +520,12 @@ class ContactsManager : public Actor { void add_dialog_participants(DialogId dialog_id, const vector &user_ids, Promise &&promise); - void set_dialog_participant_status(DialogId dialog_id, UserId user_id, + void set_dialog_participant_status(DialogId dialog_id, DialogId participant_dialog_id, const tl_object_ptr &chat_member_status, Promise &&promise); - void ban_dialog_participant(DialogId dialog_id, UserId user_id, int32 banned_until_date, bool revoke_messages, - Promise &&promise); + void ban_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, int32 banned_until_date, + bool revoke_messages, Promise &&promise); DialogParticipant get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, int64 &random_id, bool force, Promise &&promise); @@ -1488,8 +1488,8 @@ class ContactsManager : public Actor { void change_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status, Promise &&promise); - void change_channel_participant_status(ChannelId channel_id, UserId user_id, DialogParticipantStatus status, - Promise &&promise); + void change_channel_participant_status(ChannelId channel_id, DialogId participant_dialog_id, + DialogParticipantStatus status, Promise &&promise); void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise &&promise); @@ -1508,14 +1508,16 @@ class ContactsManager : public Actor { tl_object_ptr &&channel_participants, Promise &&promise); - void change_channel_participant_status_impl(ChannelId channel_id, UserId user_id, DialogParticipantStatus status, - DialogParticipantStatus old_status, Promise &&promise); + void change_channel_participant_status_impl(ChannelId channel_id, DialogId participant_dialog_id, + DialogParticipantStatus status, DialogParticipantStatus old_status, + Promise &&promise); void promote_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status, DialogParticipantStatus old_status, Promise &&promise); - void restrict_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status, - DialogParticipantStatus old_status, Promise &&promise); + void restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + DialogParticipantStatus status, DialogParticipantStatus old_status, + Promise &&promise); void transfer_channel_ownership(ChannelId channel_id, UserId user_id, tl_object_ptr input_check_password, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index d1a071e86..565bd5449 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6323,8 +6323,8 @@ void Td::on_request(uint64 id, const td_api::leaveChat &request) { td_api::make_object(status.get_rank(), status.is_anonymous(), false); } } - contacts_manager_->set_dialog_participant_status(dialog_id, contacts_manager_->get_my_id(), std::move(new_status), - std::move(promise)); + contacts_manager_->set_dialog_participant_status(dialog_id, DialogId(contacts_manager_->get_my_id()), + std::move(new_status), std::move(promise)); } void Td::on_request(uint64 id, const td_api::addChatMember &request) { @@ -6343,13 +6343,15 @@ void Td::on_request(uint64 id, const td_api::addChatMembers &request) { void Td::on_request(uint64 id, td_api::setChatMemberStatus &request) { CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_dialog_participant_status(DialogId(request.chat_id_), UserId(request.user_id_), + contacts_manager_->set_dialog_participant_status(DialogId(request.chat_id_), + ContactsManager::get_participant_dialog_id(request.member_id_), request.status_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::banChatMember &request) { CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->ban_dialog_participant(DialogId(request.chat_id_), UserId(request.user_id_), + contacts_manager_->ban_dialog_participant(DialogId(request.chat_id_), + ContactsManager::get_participant_dialog_id(request.member_id_), request.banned_until_date_, request.revoke_messages_, std::move(promise)); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d6b5ecbdf..dba8ea74d 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3646,11 +3646,11 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(chat_id), as_user_ids(user_ids))); } else if (op == "bcm") { string chat_id; - string user_id; + string member_id; int32 banned_until_date; bool revoke_messages; - get_args(args, chat_id, user_id, banned_until_date, revoke_messages); - send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), + get_args(args, chat_id, member_id, banned_until_date, revoke_messages); + send_request(td_api::make_object(as_chat_id(chat_id), as_message_sender(member_id), banned_until_date, revoke_messages)); } else if (op == "spolla") { string chat_id; @@ -3679,10 +3679,10 @@ class CliClient final : public Actor { if (op == "scms") { string chat_id; - string user_id; + string member_id; string status_str; td_api::object_ptr status; - get_args(args, chat_id, user_id, status_str); + get_args(args, chat_id, member_id, status_str); if (status_str == "member") { status = td_api::make_object(); } else if (status_str == "left") { @@ -3738,7 +3738,7 @@ class CliClient final : public Actor { true, 0, td_api::make_object(true, true, true, true, true, true, true, true)); } if (status != nullptr) { - send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id), + send_request(td_api::make_object(as_chat_id(chat_id), as_message_sender(member_id), std::move(status))); } else { LOG(ERROR) << "Unknown status \"" << status_str << "\""; @@ -3764,14 +3764,14 @@ class CliClient final : public Actor { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "dcm") { string chat_id; - string user_id_str; - get_args(args, chat_id, user_id_str); - auto user_id = as_user_id(user_id_str); + string member_id; + get_args(args, chat_id, member_id); td_api::object_ptr status = td_api::make_object(); - if (user_id == my_id_) { + if (as_user_id(member_id) == my_id_) { status = td_api::make_object(); } - send_request(td_api::make_object(as_chat_id(chat_id), user_id, std::move(status))); + send_request(td_api::make_object(as_chat_id(chat_id), as_message_sender(member_id), + std::move(status))); } else if (op == "sn") { string first_name; string last_name;