From 206cd55479c9ddf44ee855190717ae2d65795b34 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 24 Mar 2021 23:40:13 +0300 Subject: [PATCH] Support chat-members in getChatMember. --- td/generate/scheme/td_api.tl | 4 +- td/telegram/ContactsManager.cpp | 94 ++++++++++++++++++++++----------- td/telegram/ContactsManager.h | 9 ++-- td/telegram/Td.cpp | 22 +++++--- td/telegram/Td.h | 2 +- td/telegram/cli.cpp | 6 +-- 6 files changed, 87 insertions(+), 50 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 8e30b2f2a..d42fd0018 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -4393,8 +4393,8 @@ canTransferOwnership = CanTransferOwnershipResult; //@chat_id Chat identifier @user_id Identifier of the user to which transfer the ownership. The ownership can't be transferred to a bot or to a deleted user @password The password of the current user transferChatOwnership chat_id:int53 user_id:int32 password:string = Ok; -//@description Returns information about a single member of a chat @chat_id Chat identifier @user_id User identifier -getChatMember chat_id:int53 user_id:int32 = ChatMember; +//@description Returns information about a single member of a chat @chat_id Chat identifier @member_id Member identifier +getChatMember chat_id:int53 member_id:MessageSender = ChatMember; //@description Searches for a specified query in the first name, last name and username of the members of a specified chat. Requires administrator rights in channels @chat_id Chat identifier @query Query to search for @limit The maximum number of users to be returned @filter The type of users to return. By default, chatMembersFilterMembers searchChatMembers chat_id:int53 query:string limit:int32 filter:ChatMembersFilter = ChatMembers; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 143a3c0d0..2b9e5cfe5 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -2905,13 +2905,13 @@ class GetFullChannelQuery : public Td::ResultHandler { class GetChannelParticipantQuery : public Td::ResultHandler { Promise promise_; ChannelId channel_id_; - UserId user_id_; + DialogId participant_dialog_id_; public: explicit GetChannelParticipantQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(ChannelId channel_id, UserId user_id, tl_object_ptr &&input_peer) { + void send(ChannelId channel_id, DialogId participant_dialog_id, tl_object_ptr &&input_peer) { auto input_channel = td->contacts_manager_->get_input_channel(channel_id); if (input_channel == nullptr) { return promise_.set_error(Status::Error(3, "Supergroup not found")); @@ -2920,7 +2920,7 @@ class GetChannelParticipantQuery : public Td::ResultHandler { CHECK(input_peer != nullptr); channel_id_ = channel_id; - user_id_ = user_id; + participant_dialog_id_ = participant_dialog_id; send_query(G()->net_query_creator().create( telegram_api::channels_getParticipant(std::move(input_channel), std::move(input_peer)))); } @@ -2946,11 +2946,11 @@ class GetChannelParticipantQuery : public Td::ResultHandler { void on_error(uint64 id, Status status) override { if (status.message() == "USER_NOT_PARTICIPANT") { - promise_.set_value(DialogParticipant::left(DialogId(user_id_))); + promise_.set_value(DialogParticipant::left(participant_dialog_id_)); return; } - td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelParticipantQuery"); + // td->contacts_manager_->on_get_channel_error(channel_id_, status, "GetChannelParticipantQuery"); promise_.set_error(std::move(status)); } }; @@ -6873,7 +6873,7 @@ void ContactsManager::change_channel_participant_status(ChannelId channel_id, Us }); td_->create_handler(std::move(on_result_promise)) - ->send(channel_id, user_id, std::move(input_peer)); + ->send(channel_id, DialogId(user_id), std::move(input_peer)); } void ContactsManager::change_channel_participant_status_impl(ChannelId channel_id, UserId user_id, @@ -14531,47 +14531,73 @@ void ContactsManager::ban_dialog_participant(DialogId dialog_id, UserId user_id, } } -DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, UserId user_id, int64 &random_id, - bool force, Promise &&promise) { - LOG(INFO) << "Receive GetChatMember request to get " << user_id << " in " << dialog_id << " with random_id " - << random_id; +DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, + const td_api::object_ptr &member_id, + int64 &random_id, bool force, Promise &&promise) { + LOG(INFO) << "Receive GetChatMember request to get " << to_string(member_id) << " in " << dialog_id + << " with random_id " << random_id; if (!td_->messages_manager_->have_dialog_force(dialog_id, "get_dialog_participant")) { promise.set_error(Status::Error(3, "Chat not found")); return DialogParticipant(); } + if (member_id == nullptr) { + promise.set_error(Status::Error(3, "Member must be non-empty")); + return DialogParticipant(); + } + DialogId participant_dialog_id; + switch (member_id->get_id()) { + case td_api::messageSenderUser::ID: + participant_dialog_id = + DialogId(UserId(static_cast(member_id.get())->user_id_)); + break; + case td_api::messageSenderChat::ID: + participant_dialog_id = DialogId(static_cast(member_id.get())->chat_id_); + break; + default: + UNREACHABLE(); + } + if (!participant_dialog_id.is_valid()) { + promise.set_error(Status::Error(3, "Invalid member identifier specified")); + return DialogParticipant(); + } + switch (dialog_id.get_type()) { - case DialogType::User: { - auto peer_user_id = dialog_id.get_user_id(); - if (user_id == get_my_id()) { + case DialogType::User: + if (participant_dialog_id == DialogId(get_my_id())) { promise.set_value(Unit()); - return {DialogId(user_id), peer_user_id, 0, DialogParticipantStatus::Member()}; + return {participant_dialog_id, dialog_id.get_user_id(), 0, DialogParticipantStatus::Member()}; } - if (user_id == peer_user_id) { + if (participant_dialog_id == dialog_id) { promise.set_value(Unit()); - return {DialogId(peer_user_id), user_id, 0, DialogParticipantStatus::Member()}; + return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; } - promise.set_error(Status::Error(3, "User is not a member of the private chat")); + promise.set_error(Status::Error(3, "Member not found")); break; - } case DialogType::Chat: - return get_chat_participant(dialog_id.get_chat_id(), user_id, force, std::move(promise)); + if (participant_dialog_id.get_type() != DialogType::User) { + promise.set_value(Unit()); + return DialogParticipant::left(participant_dialog_id); + } + return get_chat_participant(dialog_id.get_chat_id(), participant_dialog_id.get_user_id(), force, + std::move(promise)); case DialogType::Channel: - return get_channel_participant(dialog_id.get_channel_id(), user_id, random_id, force, std::move(promise)); + return get_channel_participant(dialog_id.get_channel_id(), participant_dialog_id, random_id, force, + std::move(promise)); case DialogType::SecretChat: { auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id()); - if (user_id == get_my_id()) { + if (participant_dialog_id == DialogId(get_my_id())) { promise.set_value(Unit()); - return {DialogId(user_id), peer_user_id.is_valid() ? peer_user_id : user_id, 0, + return {participant_dialog_id, peer_user_id.is_valid() ? peer_user_id : get_my_id(), 0, DialogParticipantStatus::Member()}; } - if (peer_user_id.is_valid() && user_id == peer_user_id) { + if (participant_dialog_id == DialogId(peer_user_id)) { promise.set_value(Unit()); - return {DialogId(peer_user_id), user_id, 0, DialogParticipantStatus::Member()}; + return {participant_dialog_id, get_my_id(), 0, DialogParticipantStatus::Member()}; } - promise.set_error(Status::Error(3, "User is not a member of the secret chat")); + promise.set_error(Status::Error(3, "Member not found")); break; } case DialogType::None: @@ -14794,9 +14820,10 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string & })}); } -DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, UserId user_id, int64 &random_id, - bool force, Promise &&promise) { - LOG(INFO) << "Trying to get " << user_id << " as member of " << channel_id << " with random_id " << random_id; +DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, + int64 &random_id, bool force, Promise &&promise) { + LOG(INFO) << "Trying to get " << participant_dialog_id << " as member of " << channel_id << " with random_id " + << random_id; if (random_id != 0) { // request has already been sent before auto it = received_channel_participant_.find(random_id); @@ -14807,13 +14834,15 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, return result; } - 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) { promise.set_error(Status::Error(6, "User not found")); return DialogParticipant(); } - if (!td_->auth_manager_->is_bot() && is_user_bot(user_id)) { + if (!td_->auth_manager_->is_bot() && participant_dialog_id.get_type() == DialogType::User && + is_user_bot(participant_dialog_id.get_user_id())) { + auto user_id = participant_dialog_id.get_user_id(); auto u = get_user(user_id); CHECK(u != nullptr); if (is_bot_info_expired(user_id, u->bot_info_version)) { @@ -14831,7 +14860,8 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, } while (random_id == 0 || received_channel_participant_.find(random_id) != received_channel_participant_.end()); received_channel_participant_[random_id]; // reserve place for result - LOG(DEBUG) << "Get info about " << user_id << " membership in the " << channel_id << " with random_id " << random_id; + LOG(DEBUG) << "Get info about " << participant_dialog_id << " membership in the " << channel_id << " with random_id " + << random_id; auto on_result_promise = PromiseCreator::lambda( [this, random_id, promise = std::move(promise)](Result r_dialog_participant) mutable { @@ -14851,7 +14881,7 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, }); td_->create_handler(std::move(on_result_promise)) - ->send(channel_id, user_id, std::move(input_peer)); + ->send(channel_id, participant_dialog_id, std::move(input_peer)); return DialogParticipant(); } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 241ea3874..2aa4c895c 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -525,8 +525,9 @@ class ContactsManager : public Actor { void ban_dialog_participant(DialogId dialog_id, UserId user_id, int32 banned_until_date, bool revoke_messages, Promise &&promise); - DialogParticipant get_dialog_participant(DialogId dialog_id, UserId user_id, int64 &random_id, bool force, - Promise &&promise); + DialogParticipant get_dialog_participant(DialogId dialog_id, + const td_api::object_ptr &member_id, int64 &random_id, + bool force, Promise &&promise); void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter, bool without_bot_info, Promise &&promise); @@ -1425,8 +1426,8 @@ class ContactsManager : public Actor { DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise &&promise); - DialogParticipant get_channel_participant(ChannelId channel_id, UserId user_id, int64 &random_id, bool force, - Promise &&promise); + DialogParticipant get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, int64 &random_id, + bool force, Promise &&promise); static string get_dialog_administrators_database_key(DialogId dialog_id); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 4f9f1c3bf..c89722df9 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1940,26 +1940,32 @@ class UpgradeGroupChatToSupergroupChatRequest : public RequestActor<> { class GetChatMemberRequest : public RequestActor<> { DialogId dialog_id_; - UserId user_id_; + td_api::object_ptr member_id_; int64 random_id_; DialogParticipant dialog_participant_; void do_run(Promise &&promise) override { - dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, user_id_, random_id_, + dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, member_id_, random_id_, get_tries() < 3, std::move(promise)); } void do_send_result() override { - if (!td->contacts_manager_->have_user(user_id_)) { - return send_error(Status::Error(3, "User not found")); + auto dialog_id = dialog_participant_.dialog_id; + if ((dialog_id.get_type() == DialogType::User && !td->contacts_manager_->have_user(dialog_id.get_user_id())) || + !td->messages_manager_->have_dialog(dialog_id)) { + return send_error(Status::Error(3, "Member not found")); } send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_)); } public: - GetChatMemberRequest(ActorShared td, uint64 request_id, int64 dialog_id, int32 user_id) - : RequestActor(std::move(td), request_id), dialog_id_(dialog_id), user_id_(user_id), random_id_(0) { + GetChatMemberRequest(ActorShared td, uint64 request_id, int64 dialog_id, + td_api::object_ptr &&member_id) + : RequestActor(std::move(td), request_id) + , dialog_id_(dialog_id) + , member_id_(std::move(member_id)) + , random_id_(0) { set_tries(3); } }; @@ -6370,8 +6376,8 @@ void Td::on_request(uint64 id, td_api::transferChatOwnership &request) { std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getChatMember &request) { - CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, request.user_id_); +void Td::on_request(uint64 id, td_api::getChatMember &request) { + CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, std::move(request.member_id_)); } void Td::on_request(uint64 id, td_api::searchChatMembers &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 1b39d9420..8061c38bc 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -809,7 +809,7 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::transferChatOwnership &request); - void on_request(uint64 id, const td_api::getChatMember &request); + void on_request(uint64 id, td_api::getChatMember &request); void on_request(uint64 id, td_api::searchChatMembers &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 9609df64d..d6b5ecbdf 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2452,9 +2452,9 @@ class CliClient final : public Actor { get_chat_members_filter(filter))); } else if (op == "gcm") { string chat_id; - string user_id; - get_args(args, chat_id, user_id); - send_request(td_api::make_object(as_chat_id(chat_id), as_user_id(user_id))); + string member_id; + get_args(args, chat_id, member_id); + send_request(td_api::make_object(as_chat_id(chat_id), as_message_sender(member_id))); } else if (op == "GetChatAdministrators") { string chat_id = args; send_request(td_api::make_object(as_chat_id(chat_id)));