From 43d8e6ccdbf5895d91660e68188e9314b9d029b8 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 11 Nov 2019 19:14:32 +0300 Subject: [PATCH] Return administrator ranks from getChatAdministrators. GitOrigin-RevId: 8e3e540ae73aebacf9a3fe954b2b81511c999953 --- CMakeLists.txt | 2 + td/generate/scheme/td_api.tl | 11 ++- td/generate/scheme/td_api.tlo | Bin 163636 -> 163984 bytes td/telegram/ContactsManager.cpp | 130 ++++++++++++++++++---------- td/telegram/ContactsManager.h | 13 +-- td/telegram/DialogAdministrator.cpp | 26 ++++++ td/telegram/DialogAdministrator.h | 80 +++++++++++++++++ td/telegram/MessagesManager.cpp | 3 +- td/telegram/MessagesManager.h | 3 +- td/telegram/Td.cpp | 10 ++- td/telegram/cli.cpp | 3 + 11 files changed, 224 insertions(+), 57 deletions(-) create mode 100644 td/telegram/DialogAdministrator.cpp create mode 100644 td/telegram/DialogAdministrator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 367bb4746..0b08f217e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,6 +373,7 @@ set(TDLIB_SOURCE td/telegram/DelayDispatcher.cpp td/telegram/DeviceTokenManager.cpp td/telegram/DhCache.cpp + td/telegram/DialogAdministrator.cpp td/telegram/DialogDb.cpp td/telegram/DialogId.cpp td/telegram/DialogLocation.cpp @@ -518,6 +519,7 @@ set(TDLIB_SOURCE td/telegram/DeviceTokenManager.h td/telegram/DhCache.h td/telegram/DhConfig.h + td/telegram/DialogAdministrator.h td/telegram/DialogDate.h td/telegram/DialogDb.h td/telegram/DialogId.h diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b55e005e6..5fa6a6394 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -321,6 +321,13 @@ userProfilePhotos total_count:int32 photos:vector = UserProfil users total_count:int32 user_ids:vector = Users; +//@description Contains information about a chat administrator @user_id User identifier of the administrator @custom_title Custom title of the administrator +chatAdministrator user_id:int32 custom_title:string = ChatAdministrator; + +//@description Represents a list of chat administrators @administrators A list of chat administrators +chatAdministrators administrators:vector = ChatAdministrators; + + //@description Describes actions that a user is allowed to take in a chat //@can_send_messages True, if the user can send text messages, contacts, locations, and venues //@can_send_media_messages True, if the user can send audio files, documents, photos, videos, video notes, and voice notes. Implies can_send_messages permissions @@ -3532,8 +3539,8 @@ getChatMember chat_id:int53 user_id:int32 = 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; -//@description Returns a list of users who are administrators of the chat @chat_id Chat identifier -getChatAdministrators chat_id:int53 = Users; +//@description Returns a list of administrators of the chat with their custom titles @chat_id Chat identifier +getChatAdministrators chat_id:int53 = ChatAdministrators; //@description Clears draft messages in all chats @exclude_secret_chats If true, local draft messages in secret chats will not be cleared diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index b5bc66cea47039f2dbc771ca88d1196d1c807947..98a0d1de8f9c2236595332df520b9aa2490738c3 100644 GIT binary patch delta 289 zcmdn;k8?sJ7w@Cl`c@23@M9xyJFCd48S7mHoih?k98+>L^D>J|iV{mE2k^*9*#2;7 z6hf28FDho3{D4tn^AuJNRmMM?=W0FHkO7;JjA}xD5d#BAe0t0RMxDtoQdA~4)N{Cj zL}0dGmE(#5TY;gom;oey^O%qiBT%vQv-_HSi3qpl7fr6ym6HG&1(F7VB4;)o4%@ba rAZ^Vh!P`rM8FMx&?B2!~BbuICg2fA93#J=9Wi(&`=~-^V%2WjaWBX{k delta 76 zcmbQx$hGAkC-0-#`c@23@NFY+JL~2ztQ@M0zc&BXdaTiWCuIAb5XOX!ERBD?net_query_creator().create(create_storer(telegram_api::channels_getParticipants( std::move(input_channel), telegram_api::make_object(), 0, @@ -2479,18 +2481,23 @@ class GetChannelAdministratorsQuery : public Td::ResultHandler { case telegram_api::channels_channelParticipants::ID: { auto participants = telegram_api::move_object_as(participants_ptr); td->contacts_manager_->on_get_users(std::move(participants->users_), "GetChannelAdministratorsQuery"); - vector administrator_user_ids; - administrator_user_ids.reserve(participants->participants_.size()); + vector administrators; + administrators.reserve(participants->participants_.size()); for (auto &participant : participants->participants_) { - UserId user_id; - downcast_call(*participant, [&user_id](auto &participant) { user_id = UserId(participant.user_id_); }); - if (user_id.is_valid()) { - administrator_user_ids.push_back(user_id); + DialogParticipant dialog_participant = + td->contacts_manager_->get_dialog_participant(channel_id_, std::move(participant)); + if (!dialog_participant.user_id.is_valid() || !dialog_participant.status.is_administrator()) { + LOG(ERROR) << "Receive " << dialog_participant.user_id << " with status " << dialog_participant.status + << " as an administrator of " << channel_id_; + continue; } + administrators.emplace_back(dialog_participant.user_id, dialog_participant.status.get_rank()); } - td->contacts_manager_->on_update_dialog_administrators(DialogId(channel_id_), std::move(administrator_user_ids), - true); + td->contacts_manager_->on_update_channel_administrator_count(channel_id_, + narrow_cast(administrators.size())); + td->contacts_manager_->on_update_dialog_administrators(DialogId(channel_id_), std::move(administrators), true); + break; } case telegram_api::channels_channelParticipantsNotModified::ID: @@ -7901,18 +7908,18 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool chat_full->need_save_to_database |= chat_full->is_changed; chat_full->is_changed = false; if (chat_full->need_send_update) { - vector administrator_user_ids; + vector administrators; vector bot_user_ids; for (const auto &participant : chat_full->participants) { auto user_id = participant.user_id; if (participant.status.is_administrator()) { - administrator_user_ids.push_back(user_id); + administrators.emplace_back(user_id, participant.status.get_rank()); } if (is_user_bot(user_id)) { bot_user_ids.push_back(user_id); } } - on_update_dialog_administrators(DialogId(chat_id), std::move(administrator_user_ids), chat_full->version != -1); + on_update_dialog_administrators(DialogId(chat_id), std::move(administrators), chat_full->version != -1); td_->messages_manager_->on_dialog_bots_updated(DialogId(chat_id), std::move(bot_user_ids)); send_closure( @@ -9165,33 +9172,34 @@ void ContactsManager::on_get_channel_participants_success( filter.is_recent() && total_count != 0 && total_count < max_participant_count ? total_count : -1; int32 administrator_count = filter.is_administrators() ? total_count : -1; if (is_full && (filter.is_administrators() || filter.is_bots() || filter.is_recent())) { - vector administrator_user_ids; + vector administrators; vector bot_user_ids; { - auto user_ids = transform(result, [](const DialogParticipant &participant) { return participant.user_id; }); if (filter.is_recent()) { for (const auto &participant : result) { if (participant.status.is_administrator()) { - administrator_user_ids.push_back(participant.user_id); + administrators.emplace_back(participant.user_id, participant.status.get_rank()); } if (is_user_bot(participant.user_id)) { bot_user_ids.push_back(participant.user_id); } } - administrator_count = narrow_cast(administrator_user_ids.size()); + administrator_count = narrow_cast(administrators.size()); if (get_channel_type(channel_id) == ChannelType::Megagroup && !td_->auth_manager_->is_bot()) { cached_channel_participants_[channel_id] = result; update_channel_online_member_count(channel_id, true); } } else if (filter.is_administrators()) { - administrator_user_ids = std::move(user_ids); + for (const auto &participant : result) { + administrators.emplace_back(participant.user_id, participant.status.get_rank()); + } } else if (filter.is_bots()) { - bot_user_ids = std::move(user_ids); + bot_user_ids = transform(result, [](const DialogParticipant &participant) { return participant.user_id; }); } } if (filter.is_administrators() || filter.is_recent()) { - on_update_dialog_administrators(DialogId(channel_id), std::move(administrator_user_ids), true); + on_update_dialog_administrators(DialogId(channel_id), std::move(administrators), true); } if (filter.is_bots() || filter.is_recent()) { on_update_channel_bot_user_ids(channel_id, std::move(bot_user_ids)); @@ -9356,19 +9364,36 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId update_channel(c, channel_id); } - if (new_status.is_administrator() != old_status.is_administrator()) { + if (new_status.is_administrator() != old_status.is_administrator() || + new_status.get_rank() != old_status.get_rank()) { DialogId dialog_id(channel_id); auto administrators_it = dialog_administrators_.find(dialog_id); if (administrators_it != dialog_administrators_.end()) { - auto user_ids = administrators_it->second; + auto administrators = administrators_it->second; if (new_status.is_administrator()) { - if (!td::contains(user_ids, user_id)) { - user_ids.push_back(user_id); - on_update_dialog_administrators(dialog_id, std::move(user_ids), true); + bool is_found = false; + for (auto &administrator : administrators) { + if (administrator.get_user_id() == user_id) { + is_found = true; + if (administrator.get_rank() != new_status.get_rank()) { + administrator = DialogAdministrator(user_id, new_status.get_rank()); + on_update_dialog_administrators(dialog_id, std::move(administrators), true); + } + break; + } + } + if (!is_found) { + administrators.emplace_back(user_id, new_status.get_rank()); + on_update_dialog_administrators(dialog_id, std::move(administrators), true); } } else { - if (td::remove(user_ids, user_id)) { - on_update_dialog_administrators(dialog_id, std::move(user_ids), true); + size_t i = 0; + while (i != administrators.size() && administrators[i].get_user_id() != user_id) { + i++; + } + if (i != administrators.size()) { + administrators.erase(administrators.begin() + i); + on_update_dialog_administrators(dialog_id, std::move(administrators), true); } } } @@ -11597,13 +11622,15 @@ void ContactsManager::send_get_channel_participants_query(ChannelId channel_id, ->send(channel_id, std::move(filter), offset, limit, random_id); } -vector ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise) { +vector ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, + Promise &&promise) { auto it = dialog_administrators_.find(dialog_id); if (it != dialog_administrators_.end()) { promise.set_value(Unit()); if (left_tries >= 2) { - auto hash = - get_vector_hash(transform(it->second, [](UserId user_id) { return static_cast(user_id.get()); })); + auto hash = get_vector_hash(transform(it->second, [](const DialogAdministrator &administrator) { + return static_cast(administrator.get_user_id().get()); + })); reload_dialog_administrators(dialog_id, hash, Auto()); // update administrators cache } return it->second; @@ -11625,7 +11652,7 @@ vector ContactsManager::get_dialog_administrators(DialogId dialog_id, in } string ContactsManager::get_dialog_administrators_database_key(DialogId dialog_id) { - return PSTRING() << "admin" << (-dialog_id.get()); + return PSTRING() << "adm" << (-dialog_id.get()); } void ContactsManager::load_dialog_administrators(DialogId dialog_id, Promise &&promise) { @@ -11649,50 +11676,63 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo return; } - vector user_ids; - log_event_parse(user_ids, value).ensure(); + vector administrators; + log_event_parse(administrators, value).ensure(); - LOG(INFO) << "Successfully loaded " << user_ids.size() << " administrators in " << dialog_id << " from database"; + LOG(INFO) << "Successfully loaded " << administrators.size() << " administrators in " << dialog_id + << " from database"; MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"}; load_users_multipromise.add_promise( - PromiseCreator::lambda([dialog_id, user_ids, promise = std::move(promise)](Result<> result) mutable { + PromiseCreator::lambda([dialog_id, administrators, promise = std::move(promise)](Result<> result) mutable { send_closure(G()->contacts_manager(), &ContactsManager::on_load_administrator_users_finished, dialog_id, - std::move(user_ids), std::move(result), std::move(promise)); + std::move(administrators), std::move(result), std::move(promise)); })); auto lock_promise = load_users_multipromise.get_promise(); - for (auto user_id : user_ids) { - get_user(user_id, 3, load_users_multipromise.get_promise()); + for (auto &administrator : administrators) { + get_user(administrator.get_user_id(), 3, load_users_multipromise.get_promise()); } lock_promise.set_value(Unit()); } -void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, vector user_ids, Result<> result, +void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, + vector administrators, Result<> result, Promise promise) { if (result.is_ok()) { - dialog_administrators_.emplace(dialog_id, std::move(user_ids)); + dialog_administrators_.emplace(dialog_id, std::move(administrators)); } promise.set_value(Unit()); } -void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector administrator_user_ids, +void ContactsManager::on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count) { + auto channel_full = get_channel_full_force(channel_id); + if (channel_full != nullptr && channel_full->administrator_count != administrator_count) { + channel_full->administrator_count = administrator_count; + channel_full->is_changed = true; + update_channel_full(channel_full, channel_id); + } +} + +void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector &&administrators, bool have_access) { - LOG(INFO) << "Update administrators in " << dialog_id << " to " << format::as_array(administrator_user_ids); + LOG(INFO) << "Update administrators in " << dialog_id << " to " << format::as_array(administrators); if (have_access) { - std::sort(administrator_user_ids.begin(), administrator_user_ids.end(), - [](UserId lhs, UserId rhs) { return lhs.get() < rhs.get(); }); + std::sort(administrators.begin(), administrators.end(), + [](const DialogAdministrator &lhs, const DialogAdministrator &rhs) { + return lhs.get_user_id().get() < rhs.get_user_id().get(); + }); auto it = dialog_administrators_.find(dialog_id); if (it != dialog_administrators_.end()) { - if (it->second == administrator_user_ids) { + if (it->second == administrators) { return; } - it->second = std::move(administrator_user_ids); + it->second = std::move(administrators); } else { - it = dialog_administrators_.emplace(dialog_id, std::move(administrator_user_ids)).first; + it = dialog_administrators_.emplace(dialog_id, std::move(administrators)).first; } if (G()->parameters().use_chat_info_db) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 672f217a3..8181ef739 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -13,6 +13,7 @@ #include "td/telegram/ChannelId.h" #include "td/telegram/ChatId.h" #include "td/telegram/Contact.h" +#include "td/telegram/DialogAdministrator.h" #include "td/telegram/DialogId.h" #include "td/telegram/DialogLocation.h" #include "td/telegram/DialogParticipant.h" @@ -186,10 +187,12 @@ class ContactsManager : public Actor { void on_update_channel_location(ChannelId channel_id, const DialogLocation &location); void on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available); void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions); + void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count); void on_update_peer_located(vector> &&peers, bool from_update); - void on_update_dialog_administrators(DialogId dialog_id, vector administrator_user_ids, bool have_access); + void on_update_dialog_administrators(DialogId dialog_id, vector &&administrators, + bool have_access); void speculative_add_channel_participants(ChannelId channel_id, const vector &added_user_ids, UserId inviter_user_id, int32 date, bool by_me); @@ -455,7 +458,7 @@ class ContactsManager : public Actor { DialogParticipant get_dialog_participant(ChannelId channel_id, tl_object_ptr &&participant_ptr) const; - vector get_dialog_administrators(DialogId chat_id, int left_tries, Promise &&promise); + vector get_dialog_administrators(DialogId chat_id, int left_tries, Promise &&promise); int32 get_user_id_object(UserId user_id, const char *source) const; @@ -1209,8 +1212,8 @@ class ContactsManager : public Actor { void on_load_dialog_administrators_from_database(DialogId dialog_id, string value, Promise &&promise); - void on_load_administrator_users_finished(DialogId dialog_id, vector user_ids, Result<> result, - Promise promise); + void on_load_administrator_users_finished(DialogId dialog_id, vector administrators, + Result<> result, Promise promise); void reload_dialog_administrators(DialogId dialog_id, int32 hash, Promise &&promise); @@ -1335,7 +1338,7 @@ class ContactsManager : public Actor { QueryCombiner get_chat_full_queries_{"GetChatFullCombiner", 2.0}; QueryCombiner get_channel_full_queries_{"GetChannelFullCombiner", 2.0}; - std::unordered_map, DialogIdHash> dialog_administrators_; + std::unordered_map, DialogIdHash> dialog_administrators_; class UploadProfilePhotoCallback; std::shared_ptr upload_profile_photo_callback_; diff --git a/td/telegram/DialogAdministrator.cpp b/td/telegram/DialogAdministrator.cpp new file mode 100644 index 000000000..583bf6e01 --- /dev/null +++ b/td/telegram/DialogAdministrator.cpp @@ -0,0 +1,26 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/DialogAdministrator.h" + +#include "td/telegram/ContactsManager.h" + +namespace td { + +td_api::object_ptr DialogAdministrator::get_chat_administrator_object( + const ContactsManager *contacts_manager) const { + CHECK(contacts_manager != nullptr); + CHECK(user_id_.is_valid()); + return td_api::make_object( + contacts_manager->get_user_id_object(user_id_, "get_chat_administrator_object"), rank_); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const DialogAdministrator &administrator) { + return string_builder << "DialogAdministrator[" << administrator.user_id_ << ", title = " << administrator.rank_ + << "]"; +} + +} // namespace td diff --git a/td/telegram/DialogAdministrator.h b/td/telegram/DialogAdministrator.h new file mode 100644 index 000000000..8dc3ff3dc --- /dev/null +++ b/td/telegram/DialogAdministrator.h @@ -0,0 +1,80 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/UserId.h" + +#include "td/utils/common.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" + +namespace td { + +class ContactsManager; + +class DialogAdministrator { + UserId user_id_; + string rank_; + + friend StringBuilder &operator<<(StringBuilder &string_builder, const DialogAdministrator &location); + + public: + DialogAdministrator() = default; + + DialogAdministrator(UserId user_id, const string &rank) : user_id_(user_id), rank_(rank) { + } + + td_api::object_ptr get_chat_administrator_object( + const ContactsManager *contacts_manager) const; + + UserId get_user_id() const { + return user_id_; + } + + const string &get_rank() const { + return rank_; + } + + template + void store(StorerT &storer) const { + using td::store; + bool has_rank = !rank_.empty(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_rank); + END_STORE_FLAGS(); + store(user_id_, storer); + if (has_rank) { + store(rank_, storer); + } + } + + template + void parse(ParserT &parser) { + using td::parse; + bool has_rank; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_rank); + END_PARSE_FLAGS(); + parse(user_id_, parser); + if (has_rank) { + parse(rank_, parser); + } + } +}; + +inline bool operator==(const DialogAdministrator &lhs, const DialogAdministrator &rhs) { + return lhs.get_user_id() == rhs.get_user_id() && lhs.get_rank() == rhs.get_rank(); +} + +inline bool operator!=(const DialogAdministrator &lhs, const DialogAdministrator &rhs) { + return !(lhs == rhs); +} + +StringBuilder &operator<<(StringBuilder &string_builder, const DialogAdministrator &administrator); + +} // namespace td diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b5f8535ba..7ce7af47e 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -23571,7 +23571,8 @@ std::pair> MessagesManager::search_dialog_parti return {}; } -vector MessagesManager::get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise) { +vector MessagesManager::get_dialog_administrators(DialogId dialog_id, int left_tries, + Promise &&promise) { LOG(INFO) << "Receive GetChatAdministrators request in " << dialog_id; if (!have_dialog_force(dialog_id)) { promise.set_error(Status::Error(3, "Chat not found")); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index a04c1448c..758ddd459 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -13,6 +13,7 @@ #include "td/telegram/AccessRights.h" #include "td/telegram/ChannelId.h" #include "td/telegram/Dependencies.h" +#include "td/telegram/DialogAdministrator.h" #include "td/telegram/DialogDate.h" #include "td/telegram/DialogDb.h" #include "td/telegram/DialogId.h" @@ -448,7 +449,7 @@ class MessagesManager : public Actor { int64 &random_id, bool force, Promise &&promise); - vector get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise); + vector get_dialog_administrators(DialogId dialog_id, int left_tries, Promise &&promise); void export_dialog_invite_link(DialogId dialog_id, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 26c551948..8bc893fe5 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1931,14 +1931,18 @@ class SearchChatMembersRequest : public RequestActor<> { class GetChatAdministratorsRequest : public RequestActor<> { DialogId dialog_id_; - vector user_ids_; + vector administrators_; void do_run(Promise &&promise) override { - user_ids_ = td->messages_manager_->get_dialog_administrators(dialog_id_, get_tries(), std::move(promise)); + administrators_ = td->messages_manager_->get_dialog_administrators(dialog_id_, get_tries(), std::move(promise)); } void do_send_result() override { - send_result(td->contacts_manager_->get_users_object(-1, user_ids_)); + auto administrator_objects = transform( + administrators_, [contacts_manager = td->contacts_manager_.get()](const DialogAdministrator &administrator) { + return administrator.get_chat_administrator_object(contacts_manager); + }); + send_result(td_api::make_object(std::move(administrator_objects))); } public: diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d019b332a..1c6844e25 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3407,6 +3407,9 @@ class CliClient final : public Actor { } else if (status_str == "admin") { status = td_api::make_object("", true, true, true, true, true, true, true, true, true); + } else if (status_str == "adminq") { + status = td_api::make_object("title", true, true, true, true, true, true, + true, true, true); } else if (status_str == "minadmin") { status = td_api::make_object("", true, true, false, false, false, false, false, false, false);