From a52b6f025f2d3b86c28ed04576fb8866a5568311 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 9 Apr 2023 21:54:40 +0300 Subject: [PATCH] Add td_api::getChatsForChatFolderInviteLink. --- td/generate/scheme/td_api.tl | 9 ++++--- td/telegram/ContactsManager.cpp | 8 ++++++ td/telegram/ContactsManager.h | 1 + td/telegram/DialogFilter.cpp | 38 +++++++++++++++++++++++++++++ td/telegram/DialogFilter.h | 2 ++ td/telegram/DialogFilterManager.cpp | 28 +++++++++++++++++++++ td/telegram/DialogFilterManager.h | 6 +++++ td/telegram/Td.cpp | 7 ++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 4 +++ 10 files changed, 101 insertions(+), 4 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 096027223..83015134a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6826,11 +6826,13 @@ getRecommendedChatFolders = RecommendedChatFolders; //@description Returns default icon name for a folder. Can be called synchronously @folder Chat folder getChatFolderDefaultIconName folder:chatFolder = ChatFolderIcon; +//@description Returns identifiers of chats from a chat folder, suitable for adding to a chat folder invite link @chat_folder_id Chat folder identifier +getChatsForChatFolderInviteLink chat_folder_id:int32 = Chats; + //@description Creates a new invite link for a chat folder. A link can be created for a chat folder if it has only pinned and included chats //@chat_folder_id Chat folder identifier //@name Name of the link; 0-32 characters -//@chat_ids Identifiers of basic group, supergroup, or channel chats to be accessible by the invite link. The chats must be public and could be join without approval by chat administrators, -//-or the user must be able to invite new members to them by an invite link. Basic groups will be automatically converted to supergroups before link creation +//@chat_ids Identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link creation createChatFolderInviteLink chat_folder_id:int32 name:string chat_ids:vector = ChatFolderInviteLink; //@description Returns invite links created by the current user for a shareable chat folder @chat_folder_id Chat folder identifier @@ -6840,8 +6842,7 @@ getChatFolderInviteLinks chat_folder_id:int32 = ChatFolderInviteLinks; //@chat_folder_id Chat folder identifier //@invite_link Invite link to be edited //@name New name of the link; 0-32 characters -//@chat_ids New identifiers of basic group, supergroup, or channel chats to be accessible by the invite link. The chats must be public and could be join without approval by chat administrators, -//-or the user must be able to invite new members to them by an invite link. Basic groups will be automatically converted to supergroups before link editing +//@chat_ids New identifiers of chats to be accessible by the invite link. Use getChatsForChatFolderInviteLink to get suitable chats. Basic groups will be automatically converted to supergroups before link editing editChatFolderInviteLink chat_folder_id:int32 invite_link:string name:string chat_ids:vector = ChatFolderInviteLink; //@description Deletes an invite link for a chat folder diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 225139033..4a852ac10 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -16980,6 +16980,14 @@ bool ContactsManager::get_channel_join_to_send(const Channel *c) { return c->join_to_send || !c->is_megagroup || !c->has_linked_channel; } +bool ContactsManager::get_channel_join_request(ChannelId channel_id) const { + auto c = get_channel(channel_id); + if (c == nullptr) { + return false; + } + return get_channel_join_request(c); +} + bool ContactsManager::get_channel_join_request(const Channel *c) { return c->join_request && c->is_megagroup && (is_channel_public(c) || c->has_linked_channel); } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index dcf95fc2e..be25b8cb2 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -634,6 +634,7 @@ class ContactsManager final : public Actor { int32 get_channel_participant_count(ChannelId channel_id) const; bool get_channel_sign_messages(ChannelId channel_id) const; bool get_channel_has_linked_channel(ChannelId channel_id) const; + bool get_channel_join_request(ChannelId channel_id) const; bool get_channel_can_be_deleted(ChannelId channel_id) const; ChannelId get_channel_linked_channel_id(ChannelId channel_id); int32 get_channel_slow_mode_delay(ChannelId channel_id); diff --git a/td/telegram/DialogFilter.cpp b/td/telegram/DialogFilter.cpp index 9841eaafd..bfb6cd10f 100644 --- a/td/telegram/DialogFilter.cpp +++ b/td/telegram/DialogFilter.cpp @@ -695,6 +695,44 @@ void DialogFilter::sort_input_dialog_ids(const Td *td, const char *source) { }); } +vector DialogFilter::get_dialogs_for_invite_link(Td *td) { + if (!excluded_dialog_ids_.empty() || exclude_muted_ || exclude_read_ || exclude_archived_ || include_contacts_ || + include_non_contacts_ || include_bots_ || include_groups_ || include_channels_) { + return {}; + } + vector result; + for_each_dialog([&](const InputDialogId &input_dialog_id) { + auto dialog_id = input_dialog_id.get_dialog_id(); + if (!td->messages_manager_->have_dialog_force(dialog_id, "get_dialogs_for_invite_link")) { + return; + } + bool is_good = false; + switch (dialog_id.get_type()) { + case DialogType::Chat: { + auto chat_id = dialog_id.get_chat_id(); + // the user can manage invite links in the chat + is_good = td->contacts_manager_->get_chat_status(chat_id).can_manage_invite_links(); + break; + } + case DialogType::Channel: { + auto channel_id = dialog_id.get_channel_id(); + // the user can manage invite links in the chat + // or the chat is a public chat, which can be joined without administrator approval + is_good = td->contacts_manager_->get_channel_status(channel_id).can_manage_invite_links() || + (td->contacts_manager_->is_channel_public(channel_id) && + !td->contacts_manager_->get_channel_join_request(channel_id)); + break; + } + default: + break; + } + if (is_good) { + result.push_back(dialog_id); + } + }); + return result; +} + vector DialogFilter::get_folder_ids() const { if (exclude_archived_ && pinned_dialog_ids_.empty() && included_dialog_ids_.empty()) { return {FolderId::main()}; diff --git a/td/telegram/DialogFilter.h b/td/telegram/DialogFilter.h index 92cda25b2..72caf697b 100644 --- a/td/telegram/DialogFilter.h +++ b/td/telegram/DialogFilter.h @@ -96,6 +96,8 @@ class DialogFilter { void sort_input_dialog_ids(const Td *td, const char *source); + vector get_dialogs_for_invite_link(Td *td); + vector get_folder_ids() const; bool need_dialog(const Td *td, const DialogFilterDialogInfo &dialog_info) const; diff --git a/td/telegram/DialogFilterManager.cpp b/td/telegram/DialogFilterManager.cpp index 0aac02597..4bc6e31b8 100644 --- a/td/telegram/DialogFilterManager.cpp +++ b/td/telegram/DialogFilterManager.cpp @@ -1852,6 +1852,34 @@ void DialogFilterManager::save_dialog_filters() { G()->td_db()->get_binlog_pmc()->set("dialog_filters", log_event_store(log_event).as_slice().str()); } +void DialogFilterManager::get_dialogs_for_dialog_filter_invite_link( + DialogFilterId dialog_filter_id, Promise> promise) { + auto dialog_filter = get_dialog_filter(dialog_filter_id); + if (dialog_filter == nullptr) { + return promise.set_error(Status::Error(400, "Chat folder not found")); + } + + auto load_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), dialog_filter_id, promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + return promise.set_error(result.move_as_error()); + } + send_closure(actor_id, &DialogFilterManager::do_get_dialogs_for_dialog_filter_invite_link, dialog_filter_id, + std::move(promise)); + }); + load_dialog_filter(dialog_filter, std::move(load_promise)); +} + +void DialogFilterManager::do_get_dialogs_for_dialog_filter_invite_link( + DialogFilterId dialog_filter_id, Promise> promise) { + auto dialog_filter = get_dialog_filter(dialog_filter_id); + if (dialog_filter == nullptr) { + return promise.set_error(Status::Error(400, "Chat folder not found")); + } + + promise.set_value(MessagesManager::get_chats_object(-1, dialog_filter->get_dialogs_for_invite_link(td_))); +} + void DialogFilterManager::create_dialog_filter_invite_link( DialogFilterId dialog_filter_id, string invite_link_name, vector dialog_ids, Promise> promise) { diff --git a/td/telegram/DialogFilterManager.h b/td/telegram/DialogFilterManager.h index e5e519bad..aadeccd33 100644 --- a/td/telegram/DialogFilterManager.h +++ b/td/telegram/DialogFilterManager.h @@ -76,6 +76,9 @@ class DialogFilterManager final : public Actor { void reorder_dialog_filters(vector dialog_filter_ids, int32 main_dialog_list_position, Promise &&promise); + void get_dialogs_for_dialog_filter_invite_link(DialogFilterId dialog_filter_id, + Promise> promise); + void create_dialog_filter_invite_link(DialogFilterId dialog_filter_id, string invite_link_name, vector dialog_ids, Promise> promise); @@ -209,6 +212,9 @@ class DialogFilterManager final : public Actor { void delete_dialogs_from_filter(const DialogFilter *dialog_filter, vector &&dialog_ids, const char *source); + void do_get_dialogs_for_dialog_filter_invite_link(DialogFilterId dialog_filter_id, + Promise> promise); + bool is_inited_ = false; bool are_dialog_filters_being_synchronized_ = false; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f48a29ca6..7b253fc70 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6143,6 +6143,13 @@ void Td::on_request(uint64 id, const td_api::reorderChatFolders &request) { request.main_chat_list_position_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getChatsForChatFolderInviteLink &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + dialog_filter_manager_->get_dialogs_for_dialog_filter_invite_link(DialogFilterId(request.chat_folder_id_), + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::createChatFolderInviteLink &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.name_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 81ffbc89d..9031f84f1 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -927,6 +927,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::reorderChatFolders &request); + void on_request(uint64 id, const td_api::getChatsForChatFolderInviteLink &request); + void on_request(uint64 id, td_api::createChatFolderInviteLink &request); void on_request(uint64 id, td_api::getChatFolderInviteLinks &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4cea42bfa..402af19bd 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4591,6 +4591,10 @@ class CliClient final : public Actor { get_args(args, main_chat_list_position, chat_folder_ids); send_request(td_api::make_object(as_chat_folder_ids(chat_folder_ids), main_chat_list_position)); + } else if (op == "gcfcfil") { + ChatFolderId chat_folder_id; + get_args(args, chat_folder_id); + send_request(td_api::make_object(chat_folder_id)); } else if (op == "crcfil") { ChatFolderId chat_folder_id; string name;