diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 332d36a5d..964fbd6cf 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5772,14 +5772,12 @@ searchChatMessages chat_id:int53 query:string sender_id:MessageSender from_messa //-For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit //@chat_list Chat list in which to search messages; pass null to search in all chats regardless of their chat list. Only Main and Archive chat lists are supported //@query Query to search for -//@offset_date The date of the message starting from which the results need to be fetched. Use 0 or any date in the future to get results from the last message -//@offset_chat_id The chat identifier of the last found message, or 0 for the first request -//@offset_message_id The message identifier of the last found message, or 0 for the first request +//@offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results //@limit The maximum number of messages to be returned; up to 100. For optimal performance, the number of returned messages is chosen by TDLib and can be smaller than the specified limit //@filter Additional filter for messages to search; pass null to search for all messages. Filters searchMessagesFilterMention, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, searchMessagesFilterFailedToSend, and searchMessagesFilterPinned are unsupported in this function //@min_date If not 0, the minimum date of the messages to return //@max_date If not 0, the maximum date of the messages to return -searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 filter:SearchMessagesFilter min_date:int32 max_date:int32 = Messages; +searchMessages chat_list:ChatList query:string offset:string limit:int32 filter:SearchMessagesFilter min_date:int32 max_date:int32 = FoundMessages; //@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance, the number of returned messages is chosen by TDLib //@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index f2c357855..31923485f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -10500,10 +10500,21 @@ void MessagesManager::on_get_messages_search_result(const string &query, int32 o auto it = found_messages_.find(random_id); CHECK(it != found_messages_.end()); - auto &result = it->second.second; + auto &result = it->second.full_message_ids; CHECK(result.empty()); + int32 last_message_date = 0; + MessageId last_message_id; + DialogId last_dialog_id; for (auto &message : messages) { + auto message_date = get_message_date(message); + auto message_id = MessageId::get_message_id(message, false); auto dialog_id = DialogId::get_message_dialog_id(message); + if (message_date > 0 && message_id.is_valid() && dialog_id.is_valid()) { + last_message_date = message_date; + last_message_id = message_id; + last_dialog_id = dialog_id; + } + auto new_full_message_id = on_get_message(std::move(message), false, dialog_id.get_type() == DialogType::Channel, false, false, false, "search messages"); if (new_full_message_id != FullMessageId()) { @@ -10518,7 +10529,11 @@ void MessagesManager::on_get_messages_search_result(const string &query, int32 o << " messages"; total_count = static_cast(result.size()); } - it->second.first = total_count; + it->second.total_count = total_count; + if (!result.empty()) { + it->second.next_offset = PSTRING() << last_message_date << ',' << last_dialog_id.get() << ',' + << last_message_id.get_server_message_id().get(); + } promise.set_value(Unit()); } @@ -23753,10 +23768,11 @@ void MessagesManager::on_message_db_calls_result(Result re promise.set_value(Unit()); } -std::pair> MessagesManager::search_messages( - FolderId folder_id, bool ignore_folder_id, const string &query, int32 offset_date, DialogId offset_dialog_id, - MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int32 min_date, int32 max_date, - int64 &random_id, Promise &&promise) { +MessagesManager::FoundMessages MessagesManager::search_messages(FolderId folder_id, bool ignore_folder_id, + const string &query, const string &offset, int32 limit, + MessageSearchFilter filter, int32 min_date, + int32 max_date, int64 &random_id, + Promise &&promise) { if (random_id != 0) { // request has already been sent before auto it = found_messages_.find(random_id); @@ -23775,19 +23791,36 @@ std::pair> MessagesManager::search_messages( limit = MAX_SEARCH_MESSAGES; } - if (offset_date <= 0) { - offset_date = std::numeric_limits::max(); - } - if (!offset_message_id.is_valid()) { - if (offset_message_id.is_valid_scheduled()) { - promise.set_error(Status::Error(400, "Parameter offset_message_id can't be a scheduled message identifier")); - return {}; + int32 offset_date = std::numeric_limits::max(); + DialogId offset_dialog_id; + MessageId offset_message_id; + bool is_offset_valid = [&] { + if (offset.empty()) { + return true; } - offset_message_id = MessageId(); - } - if (offset_message_id != MessageId() && !offset_message_id.is_server()) { - promise.set_error( - Status::Error(400, "Parameter offset_message_id must be identifier of the last found message or 0")); + + auto parts = full_split(offset, ','); + if (parts.size() != 3) { + return false; + } + auto r_offset_date = to_integer_safe(parts[0]); + auto r_offset_dialog_id = to_integer_safe(parts[1]); + auto r_offset_message_id = to_integer_safe(parts[2]); + if (r_offset_date.is_error() || r_offset_date.ok() <= 0 || r_offset_message_id.is_error() || + r_offset_dialog_id.is_error()) { + return false; + } + offset_date = r_offset_date.ok(); + offset_message_id = MessageId(ServerMessageId(r_offset_message_id.ok())); + offset_dialog_id = DialogId(r_offset_dialog_id.ok()); + if (!offset_message_id.is_valid() || !offset_dialog_id.is_valid() || + MessagesManager::get_input_peer_force(offset_dialog_id)->get_id() == telegram_api::inputPeerEmpty::ID) { + return false; + } + return true; + }(); + if (!is_offset_valid) { + promise.set_error(Status::Error(400, "Invalid offset specified")); return {}; } @@ -23809,8 +23842,8 @@ std::pair> MessagesManager::search_messages( } while (random_id == 0 || found_messages_.count(random_id) > 0); found_messages_[random_id]; // reserve place for result - LOG(DEBUG) << "Search all messages filtered by " << filter << " with query = \"" << query << "\" from date " - << offset_date << ", " << offset_dialog_id << ", " << offset_message_id << " and limit " << limit; + LOG(DEBUG) << "Search all messages filtered by " << filter << " with query = \"" << query << "\" from offset " + << offset << " and limit " << limit; td_->create_handler(std::move(promise)) ->send(folder_id, ignore_folder_id, query, offset_date, offset_dialog_id, offset_message_id, limit, filter, diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 6e6fff89b..8d39975d6 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -766,11 +766,9 @@ class MessagesManager final : public Actor { FoundMessages offline_search_messages(DialogId dialog_id, const string &query, string offset, int32 limit, MessageSearchFilter filter, int64 &random_id, Promise &&promise); - std::pair> search_messages(FolderId folder_id, bool ignore_folder_id, - const string &query, int32 offset_date, - DialogId offset_dialog_id, MessageId offset_message_id, - int32 limit, MessageSearchFilter filter, int32 min_date, - int32 max_date, int64 &random_id, Promise &&promise); + FoundMessages search_messages(FolderId folder_id, bool ignore_folder_id, const string &query, const string &offset, + int32 limit, MessageSearchFilter filter, int32 min_date, int32 max_date, + int64 &random_id, Promise &&promise); std::pair> search_call_messages(MessageId from_message_id, int32 limit, bool only_missed, int64 &random_id, bool use_db, Promise &&promise); @@ -3553,8 +3551,7 @@ class MessagesManager final : public Actor { FlatHashMap>> found_dialog_messages_; // random_id -> [total_count, [message_id]...] FlatHashMap found_dialog_messages_dialog_id_; // random_id -> dialog_id - FlatHashMap>> - found_messages_; // random_id -> [total_count, [full_message_id]...] + FlatHashMap found_messages_; // random_id -> FoundMessages FlatHashMap>> found_call_messages_; // random_id -> [total_count, [full_message_id]...] diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f76e9d98d..1a30e618f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1422,32 +1422,27 @@ class SearchMessagesRequest final : public RequestActor<> { FolderId folder_id_; bool ignore_folder_id_; string query_; - int32 offset_date_; - DialogId offset_dialog_id_; - MessageId offset_message_id_; + string offset_; int32 limit_; MessageSearchFilter filter_; int32 min_date_; int32 max_date_; int64 random_id_; - std::pair> messages_; + MessagesManager::FoundMessages messages_; void do_run(Promise &&promise) final { - messages_ = td_->messages_manager_->search_messages(folder_id_, ignore_folder_id_, query_, offset_date_, - offset_dialog_id_, offset_message_id_, limit_, filter_, + messages_ = td_->messages_manager_->search_messages(folder_id_, ignore_folder_id_, query_, offset_, limit_, filter_, min_date_, max_date_, random_id_, std::move(promise)); } void do_send_result() final { - send_result( - td_->messages_manager_->get_messages_object(messages_.first, messages_.second, true, "SearchMessagesRequest")); + send_result(td_->messages_manager_->get_found_messages_object(messages_, "SearchMessagesRequest")); } void do_send_error(Status &&status) final { if (status.message() == "SEARCH_QUERY_EMPTY") { - messages_.first = 0; - messages_.second.clear(); + messages_ = {}; return do_send_result(); } send_error(std::move(status)); @@ -1455,15 +1450,13 @@ class SearchMessagesRequest final : public RequestActor<> { public: SearchMessagesRequest(ActorShared td, uint64 request_id, FolderId folder_id, bool ignore_folder_id, string query, - int32 offset_date, int64 offset_dialog_id, int64 offset_message_id, int32 limit, - tl_object_ptr &&filter, int32 min_date, int32 max_date) + string offset, int32 limit, tl_object_ptr &&filter, + int32 min_date, int32 max_date) : RequestActor(std::move(td), request_id) , folder_id_(folder_id) , ignore_folder_id_(ignore_folder_id) , query_(std::move(query)) - , offset_date_(offset_date) - , offset_dialog_id_(offset_dialog_id) - , offset_message_id_(offset_message_id) + , offset_(std::move(offset)) , limit_(limit) , filter_(get_message_search_filter(filter)) , min_date_(min_date) @@ -5161,13 +5154,14 @@ void Td::on_request(uint64 id, td_api::searchSecretMessages &request) { void Td::on_request(uint64 id, td_api::searchMessages &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.query_); + CLEAN_INPUT_STRING(request.offset_); DialogListId dialog_list_id(request.chat_list_); if (!dialog_list_id.is_folder()) { return send_error_raw(id, 400, "Wrong chat list specified"); } CREATE_REQUEST(SearchMessagesRequest, dialog_list_id.get_folder_id(), request.chat_list_ == nullptr, - std::move(request.query_), request.offset_date_, request.offset_chat_id_, request.offset_message_id_, - request.limit_, std::move(request.filter_), request.min_date_, request.max_date_); + std::move(request.query_), std::move(request.offset_), request.limit_, std::move(request.filter_), + request.min_date_, request.max_date_); } void Td::on_request(uint64 id, const td_api::searchCallMessages &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 8f27574dd..efed6e0da 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2318,8 +2318,8 @@ class CliClient final : public Actor { string query; string limit; string filter; - int32 from_date; - get_args(args, query, limit, filter, from_date); + string offset; + get_args(args, query, limit, filter, offset); td_api::object_ptr chat_list; if (op == "SearchA") { chat_list = td_api::make_object(); @@ -2327,9 +2327,8 @@ class CliClient final : public Actor { if (op == "SearchM") { chat_list = td_api::make_object(); } - send_request(td_api::make_object(std::move(chat_list), query, from_date, 2147483647, 0, - as_limit(limit), as_search_messages_filter(filter), 1, - 2147483647)); + send_request(td_api::make_object(std::move(chat_list), query, offset, as_limit(limit), + as_search_messages_filter(filter), 1, 2147483647)); } else if (op == "SCM") { ChatId chat_id; SearchQuery query;