diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index f41f8b68f..0787e9e92 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2026,6 +2026,9 @@ searchPublicChats query:string = Chats; //@description Searches for the specified query in the title and username of already known chats, this is an offline request. Returns chats in the order seen in the chat list @query Query to search for. If the query is empty, returns up to 20 recently found chats @limit Maximum number of chats to be returned searchChats query:string limit:int32 = Chats; +//@description Searches for the specified query in the title and username of already known chats via request to the server. Returns chats in the order seen in the chat list @query Query to search for @limit Maximum number of chats to be returned +searchChatsOnServer query:string limit:int32 = Chats; + //@description Returns a list of frequently used chats. Supported only if the chat info database is enabled @category Category of chats to be returned @limit Maximum number of chats to be returned; up to 30 getTopChats category:TopChatCategory limit:int32 = Chats; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 520543153..aaa1f9fb8 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 53060eb0c..6a3a916d2 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -484,7 +484,8 @@ class SearchPublicDialogsQuery : public Td::ResultHandler { LOG(INFO) << "Receive result for SearchPublicDialogsQuery " << to_string(dialogs); td->contacts_manager_->on_get_chats(std::move(dialogs->chats_)); td->contacts_manager_->on_get_users(std::move(dialogs->users_)); - td->messages_manager_->on_get_public_dialogs_search_result(query_, std::move(dialogs->results_)); + td->messages_manager_->on_get_public_dialogs_search_result(query_, std::move(dialogs->my_results_), + std::move(dialogs->results_)); } void on_error(uint64 id, Status status) override { @@ -6475,7 +6476,21 @@ void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_ } } +vector MessagesManager::get_peers_dialog_ids(vector> &&peers) { + vector result; + result.reserve(peers.size()); + for (auto &peer : peers) { + DialogId dialog_id(peer); + if (dialog_id.is_valid()) { + force_create_dialog(dialog_id, "get_peers_dialog_ids"); + result.push_back(dialog_id); + } + } + return result; +} + void MessagesManager::on_get_public_dialogs_search_result(const string &query, + vector> &&my_peers, vector> &&peers) { auto it = search_public_dialogs_queries_.find(query); CHECK(it != search_public_dialogs_queries_.end()); @@ -6483,17 +6498,8 @@ void MessagesManager::on_get_public_dialogs_search_result(const string &query, auto promises = std::move(it->second); search_public_dialogs_queries_.erase(it); - vector result; - result.reserve(peers.size()); - for (auto &peer : peers) { - DialogId dialog_id(peer); - if (dialog_id.is_valid()) { - force_create_dialog(dialog_id, "public dialogs search"); - result.push_back(dialog_id); - } - } - - found_public_dialogs_[query] = std::move(result); + found_public_dialogs_[query] = get_peers_dialog_ids(std::move(peers)); + found_on_server_dialogs_[query] = get_peers_dialog_ids(std::move(my_peers)); for (auto &promise : promises) { promise.set_value(Unit()); @@ -6507,7 +6513,8 @@ void MessagesManager::on_failed_public_dialogs_search(const string &query, Statu auto promises = std::move(it->second); search_public_dialogs_queries_.erase(it); - found_public_dialogs_[query]; // negative cache + found_public_dialogs_[query]; // negative cache + found_on_server_dialogs_[query]; // negative cache for (auto &promise : promises) { promise.set_error(error.clone()); @@ -10559,6 +10566,47 @@ std::pair> MessagesManager::search_dialogs(const string return {result.first, std::move(dialog_ids)}; } +vector MessagesManager::sort_dialogs_by_order(const vector &dialog_ids, int32 limit) const { + auto dialog_dates = transform(dialog_ids, [this](auto dialog_id) { + const Dialog *d = this->get_dialog(dialog_id); + CHECK(d != nullptr); + return DialogDate(d->order, dialog_id); + }); + if (static_cast(limit) >= dialog_dates.size()) { + std::sort(dialog_dates.begin(), dialog_dates.end()); + } else { + std::partial_sort(dialog_dates.begin(), dialog_dates.begin() + limit, dialog_dates.end()); + dialog_dates.resize(limit, MAX_DIALOG_DATE); + } + return transform(dialog_dates, [](auto dialog_date) { return dialog_date.get_dialog_id(); }); +} + +vector MessagesManager::search_dialogs_on_server(const string &query, int32 limit, Promise &&promise) { + LOG(INFO) << "Search chats on server with query \"" << query << "\" and limit " << limit; + + if (limit < 0) { + promise.set_error(Status::Error(400, "Limit must be non-negative")); + return {}; + } + if (limit > MAX_GET_DIALOGS) { + limit = MAX_GET_DIALOGS; + } + + if (query.empty()) { + promise.set_value(Unit()); + return {}; + } + + auto it = found_on_server_dialogs_.find(query); + if (it != found_on_server_dialogs_.end()) { + promise.set_value(Unit()); + return sort_dialogs_by_order(it->second, limit); + } + + send_search_public_dialogs_query(query, std::move(promise)); + return vector(); +} + vector MessagesManager::get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, bool force, Promise &&promise) { if (!td_->contacts_manager_->have_input_user(user_id)) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index d60a79870..829e38f1a 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -850,7 +850,8 @@ class MessagesManager : public Actor { void on_get_history(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, bool from_the_end, vector> &&messages); - void on_get_public_dialogs_search_result(const string &query, vector> &&peers); + void on_get_public_dialogs_search_result(const string &query, vector> &&my_peers, + vector> &&peers); void on_failed_public_dialogs_search(const string &query, Status &&error); void on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, UserId sender_user_id, @@ -1090,6 +1091,8 @@ class MessagesManager : public Actor { std::pair> search_dialogs(const string &query, int32 limit, Promise &&promise); + vector search_dialogs_on_server(const string &query, int32 limit, Promise &&promise); + vector get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit, bool force, Promise &&promise); @@ -2054,6 +2057,10 @@ class MessagesManager : public Actor { static tl_object_ptr get_messages_object(int32 total_count, vector> &&messages); + vector sort_dialogs_by_order(const vector &dialog_ids, int32 limit) const; + + vector get_peers_dialog_ids(vector> &&peers); + void set_dialog_last_read_inbox_message_id(Dialog *d, MessageId message_id, int32 server_unread_count, int32 local_unread_count, bool force_update, const char *source); @@ -2513,7 +2520,8 @@ class MessagesManager : public Actor { postponed_get_message_requests_; std::unordered_map>> search_public_dialogs_queries_; - std::unordered_map> found_public_dialogs_; // TODO time bound cache + std::unordered_map> found_public_dialogs_; // TODO time bound cache + std::unordered_map> found_on_server_dialogs_; // TODO time bound cache std::unordered_map, UserIdHash> found_common_dialogs_; // TODO time bound cache diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 304f9996d..8879427f7 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -908,6 +908,26 @@ class SearchChatsRequest : public RequestActor<> { } }; +class SearchChatsOnServerRequest : public RequestActor<> { + string query_; + int32 limit_; + + vector dialog_ids_; + + void do_run(Promise &&promise) override { + dialog_ids_ = td->messages_manager_->search_dialogs_on_server(query_, limit_, std::move(promise)); + } + + void do_send_result() override { + send_result(MessagesManager::get_chats_object(dialog_ids_)); + } + + public: + SearchChatsOnServerRequest(ActorShared td, uint64 request_id, string query, int32 limit) + : RequestActor(std::move(td), request_id), query_(std::move(query)), limit_(limit) { + } +}; + class GetGroupsInCommonRequest : public RequestActor<> { UserId user_id_; DialogId offset_dialog_id_; @@ -4961,6 +4981,13 @@ void Td::on_request(uint64 id, td_api::searchChats &request) { CREATE_REQUEST(SearchChatsRequest, request.query_, request.limit_); } +void Td::on_request(uint64 id, td_api::searchChatsOnServer &request) { + CHECK_AUTH(); + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.query_); + CREATE_REQUEST(SearchChatsOnServerRequest, request.query_, request.limit_); +} + void Td::on_request(uint64 id, const td_api::getGroupsInCommon &request) { CHECK_AUTH(); CHECK_IS_USER(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 87e1eac3c..56645f280 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -396,6 +396,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::searchChats &request); + void on_request(uint64 id, td_api::searchChatsOnServer &request); + void on_request(uint64 id, const td_api::addRecentlyFoundChat &request); void on_request(uint64 id, const td_api::removeRecentlyFoundChat &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index d83750471..4f6a21128 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2588,6 +2588,11 @@ class CliClient final : public Actor { string query; std::tie(limit, query) = split(args); send_request(make_tl_object(query, to_integer(limit))); + } else if (op == "scos") { + string limit; + string query; + std::tie(limit, query) = split(args); + send_request(make_tl_object(query, to_integer(limit))); } else if (op == "sco") { string limit; string query;