diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 1a9212857..e3746dfdb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6791,6 +6791,12 @@ getRecommendedChatFilters = RecommendedChatFilters; //@description Returns default icon name for a filter. Can be called synchronously @filter Chat filter getChatFilterDefaultIconName filter:chatFilter = Text; +//@description Creates a new invite link for a chat filter. A link can be created for a filter if it has only pinned and included chats +//@chat_filter_id Chat filter identifier +//@name Name of the link; 0-32 characters +//@chat_ids Identifiers of supergroup or channel chats to be accessible by the invite link. The chats must be public, or the user must be able to invite new members by an invite link +createChatFilterInviteLink chat_filter_id:int32 name:string chat_ids:vector = ChatFilterInviteLink; + //@description Changes the chat title. Supported only for basic groups, supergroups and channels. Requires can_change_info administrator right //@chat_id Chat identifier diff --git a/td/telegram/DialogFilterId.h b/td/telegram/DialogFilterId.h index 5bdd90156..fb55a2470 100644 --- a/td/telegram/DialogFilterId.h +++ b/td/telegram/DialogFilterId.h @@ -6,6 +6,8 @@ // #pragma once +#include "td/telegram/telegram_api.h" + #include "td/utils/common.h" #include "td/utils/HashTableUtils.h" #include "td/utils/StringBuilder.h" @@ -41,6 +43,10 @@ class DialogFilterId { return id; } + telegram_api::object_ptr get_input_chatlist() const { + return telegram_api::make_object(id); + } + bool operator==(const DialogFilterId &other) const { return id == other.id; } diff --git a/td/telegram/DialogFilterManager.cpp b/td/telegram/DialogFilterManager.cpp index b1751c4b7..b44fc2a30 100644 --- a/td/telegram/DialogFilterManager.cpp +++ b/td/telegram/DialogFilterManager.cpp @@ -6,10 +6,12 @@ // #include "td/telegram/DialogFilterManager.h" +#include "td/telegram/AccessRights.h" #include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DialogFilter.h" #include "td/telegram/DialogFilter.hpp" +#include "td/telegram/DialogFilterInviteLink.h" #include "td/telegram/Global.h" #include "td/telegram/logevent/LogEvent.h" #include "td/telegram/MessagesManager.h" @@ -119,6 +121,37 @@ class UpdateDialogFiltersOrderQuery final : public Td::ResultHandler { } }; +class ExportChatlistInviteQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit ExportChatlistInviteQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(DialogFilterId dialog_filter_id, const string &title, + vector> &&input_peers) { + send_query(G()->net_query_creator().create(telegram_api::chatlists_exportChatlistInvite( + dialog_filter_id.get_input_chatlist(), title, std::move(input_peers)))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for ExportChatlistInviteQuery: " << to_string(ptr); + td_->dialog_filter_manager_->on_get_dialog_filter(std::move(ptr->filter_)); + promise_.set_value(DialogFilterInviteLink(td_, std::move(ptr->invite_)).get_chat_filter_invite_link_object()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + class GetDialogsQuery final : public Td::ResultHandler { Promise promise_; bool is_single_ = false; @@ -519,7 +552,9 @@ void DialogFilterManager::on_get_recommended_dialog_filters( RecommendedDialogFilter recommended_dialog_filter; recommended_dialog_filter.dialog_filter = DialogFilter::get_dialog_filter(std::move(suggested_filter->filter_), false); - CHECK(recommended_dialog_filter.dialog_filter != nullptr); + if (recommended_dialog_filter.dialog_filter == nullptr) { + continue; + } load_dialog_filter(recommended_dialog_filter.dialog_filter.get(), false, mpas.get_promise()); recommended_dialog_filter.description = std::move(suggested_filter->description_); @@ -770,6 +805,52 @@ void DialogFilterManager::reload_dialog_filters() { td_->create_handler(std::move(promise))->send(); } +void DialogFilterManager::on_get_dialog_filter(telegram_api::object_ptr filter) { + CHECK(!td_->auth_manager_->is_bot()); + auto new_server_filter = DialogFilter::get_dialog_filter(std::move(filter), true); + if (new_server_filter == nullptr) { + return; + } + new_server_filter->sort_input_dialog_ids(td_, "on_get_dialog_filter 1"); + + auto dialog_filter_id = new_server_filter->get_dialog_filter_id(); + auto old_filter = get_dialog_filter(dialog_filter_id); + if (old_filter == nullptr) { + return; + } + bool is_server_changed = false; + bool is_changed = false; + for (auto &old_server_filter : server_dialog_filters_) { + if (old_server_filter->get_dialog_filter_id() == dialog_filter_id && *new_server_filter != *old_server_filter) { + if (!DialogFilter::are_equivalent(*old_filter, *new_server_filter)) { + auto new_filter = + DialogFilter::merge_dialog_filter_changes(old_filter, old_server_filter.get(), new_server_filter.get()); + new_filter->sort_input_dialog_ids(td_, "on_get_dialog_filter 2"); + if (*new_filter != *old_filter) { + is_changed = true; + edit_dialog_filter(std::move(new_filter), "on_get_dialog_filter"); + } + } + is_server_changed = true; + old_server_filter = std::move(new_server_filter); + break; + } + } + if (!is_server_changed) { + return; + } + + if (is_changed || !is_update_chat_filters_sent_) { + send_update_chat_filters(); + } + schedule_dialog_filters_reload(get_dialog_filters_cache_time()); + save_dialog_filters(); + + if (need_synchronize_dialog_filters()) { + synchronize_dialog_filters(); + } +} + void DialogFilterManager::on_get_dialog_filters( Result>> r_filters, bool dummy) { if (G()->close_flag()) { @@ -1261,6 +1342,29 @@ void DialogFilterManager::reorder_dialog_filters(vector dialog_f promise.set_value(Unit()); } +void DialogFilterManager::create_dialog_filter_invite_link( + DialogFilterId dialog_filter_id, string invite_link_name, vector dialog_ids, + Promise> promise) { + auto dialog_filter = get_dialog_filter(dialog_filter_id); + if (dialog_filter == nullptr) { + return promise.set_error(Status::Error(400, "Chat filter not found")); + } + vector> input_peers; + input_peers.reserve(dialog_ids.size()); + for (auto &dialog_id : dialog_ids) { + auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write); + if (input_peer == nullptr) { + return promise.set_error(Status::Error(400, "Have no access to the chat")); + } + input_peers.push_back(std::move(input_peer)); + } + if (input_peers.empty()) { + return promise.set_error(Status::Error(400, "At least one chat must be included")); + } + td_->create_handler(std::move(promise)) + ->send(dialog_filter_id, invite_link_name, std::move(input_peers)); +} + void DialogFilterManager::reorder_dialog_filters_on_server(vector dialog_filter_ids, int32 main_dialog_list_position) { CHECK(!td_->auth_manager_->is_bot()); diff --git a/td/telegram/DialogFilterManager.h b/td/telegram/DialogFilterManager.h index d8bbf6819..ccd362ead 100644 --- a/td/telegram/DialogFilterManager.h +++ b/td/telegram/DialogFilterManager.h @@ -72,6 +72,12 @@ class DialogFilterManager final : public Actor { td_api::object_ptr get_chat_filter_object(DialogFilterId dialog_filter_id); + void create_dialog_filter_invite_link(DialogFilterId dialog_filter_id, string invite_link_name, + vector dialog_ids, + Promise> promise); + + void on_get_dialog_filter(telegram_api::object_ptr filter); + void get_recommended_dialog_filters(Promise> &&promise); void load_dialog_filter(DialogFilterId dialog_filter_id, bool force, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index c171bd477..524aca4be 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6152,6 +6152,15 @@ void Td::on_request(uint64 id, const td_api::reorderChatFilters &request) { request.main_chat_list_position_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::createChatFilterInviteLink &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.name_); + CREATE_REQUEST_PROMISE(); + dialog_filter_manager_->create_dialog_filter_invite_link( + DialogFilterId(request.chat_filter_id_), std::move(request.name_), DialogId::get_dialog_ids(request.chat_ids_), + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::setChatTitle &request) { CLEAN_INPUT_STRING(request.title_); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 25e345a1c..27ffb2145 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -925,6 +925,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::reorderChatFilters &request); + void on_request(uint64 id, td_api::createChatFilterInviteLink &request); + void on_request(uint64 id, td_api::setChatTitle &request); void on_request(uint64 id, const td_api::setChatPhoto &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 0db94dc91..5789b56a1 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4585,6 +4585,13 @@ class CliClient final : public Actor { get_args(args, main_chat_list_position, chat_filter_ids); send_request(td_api::make_object(as_chat_filter_ids(chat_filter_ids), main_chat_list_position)); + } else if (op == "ccfil") { + ChatFilterId chat_filter_id; + string name; + string chat_ids; + get_args(args, chat_filter_id, name, chat_ids); + send_request( + td_api::make_object(chat_filter_id, name, as_chat_ids(chat_ids))); } else if (op == "grcf") { send_request(td_api::make_object()); } else if (op == "gcfdin") {