Support search within message thread.

GitOrigin-RevId: 8ea2ac97000527d743b5a983eed57c3dd206b76c
This commit is contained in:
levlam 2020-09-08 14:17:56 +03:00
parent 3aee352751
commit 1a6ca88777
6 changed files with 54 additions and 28 deletions

View File

@ -1842,7 +1842,7 @@ searchMessagesFilterVoiceAndVideoNote = SearchMessagesFilter;
//@description Returns only messages with mentions of the current user, or messages that are replies to their messages //@description Returns only messages with mentions of the current user, or messages that are replies to their messages
searchMessagesFilterMention = SearchMessagesFilter; searchMessagesFilterMention = SearchMessagesFilter;
//@description Returns only messages with unread mentions of the current user, or messages that are replies to their messages. When using this filter the results can't be additionally filtered by a query or by the sending user //@description Returns only messages with unread mentions of the current user, or messages that are replies to their messages. When using this filter the results can't be additionally filtered by a query, a message thread or by the sending user
searchMessagesFilterUnreadMention = SearchMessagesFilter; searchMessagesFilterUnreadMention = SearchMessagesFilter;
//@description Returns only failed to send messages. This filter can be used only if the message database is used //@description Returns only failed to send messages. This filter can be used only if the message database is used
@ -3610,7 +3610,8 @@ deleteChatHistory chat_id:int53 remove_from_chat_list:Bool revoke:Bool = Ok;
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset to get the specified message and some newer messages //@offset Specify 0 to get results from exactly the from_message_id or a negative offset to get the specified message and some newer messages
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater than -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached //@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater than -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
//@filter Filter for message content in the search results //@filter Filter for message content in the search results
searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_id:int53 offset:int32 limit:int32 filter:SearchMessagesFilter = Messages; //@message_thread_id If not 0, only messages in the specified thread will be returned; supergroups only
searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_id:int53 offset:int32 limit:int32 filter:SearchMessagesFilter message_thread_id:int53 = Messages;
//@description Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chat_id, message_id)). //@description Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chat_id, message_id)).
//-For optimal performance the number of returned messages is chosen by the library //-For optimal performance the number of returned messages is chosen by the library

Binary file not shown.

View File

@ -1591,7 +1591,7 @@ class SearchMessagesQuery : public Td::ResultHandler {
void send(DialogId dialog_id, const string &query, UserId sender_user_id, void send(DialogId dialog_id, const string &query, UserId sender_user_id,
telegram_api::object_ptr<telegram_api::InputUser> &&sender_input_user, MessageId from_message_id, telegram_api::object_ptr<telegram_api::InputUser> &&sender_input_user, MessageId from_message_id,
int32 offset, int32 limit, MessageSearchFilter filter, int64 random_id) { int32 offset, int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 random_id) {
auto input_peer = dialog_id.is_valid() ? td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read) auto input_peer = dialog_id.is_valid() ? td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read)
: make_tl_object<telegram_api::inputPeerEmpty>(); : make_tl_object<telegram_api::inputPeerEmpty>();
if (input_peer == nullptr) { if (input_peer == nullptr) {
@ -1617,9 +1617,13 @@ class SearchMessagesQuery : public Td::ResultHandler {
if (sender_input_user != nullptr) { if (sender_input_user != nullptr) {
flags |= telegram_api::messages_search::FROM_ID_MASK; flags |= telegram_api::messages_search::FROM_ID_MASK;
} }
if (top_thread_message_id.is_valid()) {
flags |= telegram_api::messages_search::TOP_MSG_ID_MASK;
}
send_query(G()->net_query_creator().create(telegram_api::messages_search( send_query(G()->net_query_creator().create(telegram_api::messages_search(
flags, std::move(input_peer), query, std::move(sender_input_user), 0, get_input_messages_filter(filter), 0, flags, std::move(input_peer), query, std::move(sender_input_user),
top_thread_message_id.get_server_message_id().get(), get_input_messages_filter(filter), 0,
std::numeric_limits<int32>::max(), from_message_id.get_server_message_id().get(), offset, limit, std::numeric_limits<int32>::max(), from_message_id.get_server_message_id().get(), offset, limit,
std::numeric_limits<int32>::max(), 0, 0))); std::numeric_limits<int32>::max(), 0, 0)));
} }
@ -18460,7 +18464,8 @@ void MessagesManager::on_read_history_finished(DialogId dialog_id, uint64 genera
std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages( std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset, DialogId dialog_id, const string &query, UserId sender_user_id, MessageId from_message_id, int32 offset,
int32 limit, MessageSearchFilter filter, int64 &random_id, bool use_db, Promise<Unit> &&promise) { int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 &random_id, bool use_db,
Promise<Unit> &&promise) {
if (random_id != 0) { if (random_id != 0) {
// request has already been sent before // request has already been sent before
auto it = found_dialog_messages_.find(random_id); auto it = found_dialog_messages_.find(random_id);
@ -18473,8 +18478,8 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
random_id = 0; random_id = 0;
} }
LOG(INFO) << "Search messages with query \"" << query << "\" in " << dialog_id << " sent by " << sender_user_id LOG(INFO) << "Search messages with query \"" << query << "\" in " << dialog_id << " sent by " << sender_user_id
<< " filtered by " << filter << " from " << from_message_id << " with offset " << offset << " and limit " << " in thread of " << top_thread_message_id << " filtered by " << filter << " from " << from_message_id
<< limit; << " with offset " << offset << " and limit " << limit;
std::pair<int32, vector<MessageId>> result; std::pair<int32, vector<MessageId>> result;
if (limit <= 0) { if (limit <= 0) {
@ -18523,6 +18528,17 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
return result; return result;
} }
if (top_thread_message_id != MessageId()) {
if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) {
promise.set_error(Status::Error(400, "Invalid message thread ID specified"));
return result;
}
if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id)) {
promise.set_error(Status::Error(400, "Can't filter by message thread ID in the chat"));
return result;
}
}
do { do {
random_id = Random::secure_int64(); random_id = Random::secure_int64();
} while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end()); } while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end());
@ -18534,14 +18550,18 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
return result; return result;
} }
if (input_user != nullptr) { if (input_user != nullptr) {
promise.set_error(Status::Error(6, "Non-empty sender user is unsupported with the specified filter")); promise.set_error(Status::Error(6, "Filtering by sender user is unsupported with the specified filter"));
return result;
}
if (top_thread_message_id != MessageId()) {
promise.set_error(Status::Error(6, "Filtering by message thread is unsupported with the specified filter"));
return result; return result;
} }
} }
// Trying to use database // Trying to use database
if (use_db && query.empty() && G()->parameters().use_message_db && filter != MessageSearchFilter::Empty && if (use_db && query.empty() && G()->parameters().use_message_db && filter != MessageSearchFilter::Empty &&
input_user == nullptr) { // TODO support filter by users in the database input_user == nullptr && top_thread_message_id == MessageId()) { // TODO support filter by users in the database
MessageId first_db_message_id = get_first_database_message_id_by_index(d, filter); MessageId first_db_message_id = get_first_database_message_id_by_index(d, filter);
int32 message_count = d->message_count_by_index[message_search_filter_index(filter)]; int32 message_count = d->message_count_by_index[message_search_filter_index(filter)];
auto fixed_from_message_id = from_message_id; auto fixed_from_message_id = from_message_id;
@ -18577,7 +18597,8 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
} }
LOG(DEBUG) << "Search messages on server in " << dialog_id << " with query \"" << query << "\" from user " LOG(DEBUG) << "Search messages on server in " << dialog_id << " with query \"" << query << "\" from user "
<< sender_user_id << " from " << from_message_id << " and with limit " << limit; << sender_user_id << " in thread of " << top_thread_message_id << " from " << from_message_id
<< " and with limit " << limit;
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::None: case DialogType::None:
@ -18586,7 +18607,7 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
case DialogType::Channel: case DialogType::Channel:
td_->create_handler<SearchMessagesQuery>(std::move(promise)) td_->create_handler<SearchMessagesQuery>(std::move(promise))
->send(dialog_id, query, sender_user_id, std::move(input_user), from_message_id, offset, limit, filter, ->send(dialog_id, query, sender_user_id, std::move(input_user), from_message_id, offset, limit, filter,
random_id); top_thread_message_id, random_id);
break; break;
case DialogType::SecretChat: case DialogType::SecretChat:
if (filter == MessageSearchFilter::UnreadMention) { if (filter == MessageSearchFilter::UnreadMention) {
@ -18675,7 +18696,7 @@ std::pair<int32, vector<FullMessageId>> MessagesManager::search_call_messages(Me
LOG(DEBUG) << "Search call messages on server from " << from_message_id << " and with limit " << limit; LOG(DEBUG) << "Search call messages on server from " << from_message_id << " and with limit " << limit;
td_->create_handler<SearchMessagesQuery>(std::move(promise)) td_->create_handler<SearchMessagesQuery>(std::move(promise))
->send(DialogId(), "", UserId(), nullptr, from_message_id, 0, limit, filter, random_id); ->send(DialogId(), "", UserId(), nullptr, from_message_id, 0, limit, filter, MessageId(), random_id);
return result; return result;
} }
@ -19549,7 +19570,7 @@ int32 MessagesManager::get_dialog_message_count(DialogId dialog_id, MessageSearc
case DialogType::Chat: case DialogType::Chat:
case DialogType::Channel: case DialogType::Channel:
td_->create_handler<SearchMessagesQuery>(std::move(promise)) td_->create_handler<SearchMessagesQuery>(std::move(promise))
->send(dialog_id, "", UserId(), nullptr, MessageId(), 0, 1, filter, random_id); ->send(dialog_id, "", UserId(), nullptr, MessageId(), 0, 1, filter, MessageId(), random_id);
break; break;
case DialogType::None: case DialogType::None:
case DialogType::SecretChat: case DialogType::SecretChat:

View File

@ -661,7 +661,8 @@ class MessagesManager : public Actor {
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query, std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
UserId sender_user_id, MessageId from_message_id, UserId sender_user_id, MessageId from_message_id,
int32 offset, int32 limit, MessageSearchFilter filter, int32 offset, int32 limit, MessageSearchFilter filter,
int64 &random_id, bool use_db, Promise<Unit> &&promise); MessageId top_thread_message_id, int64 &random_id,
bool use_db, Promise<Unit> &&promise);
struct FoundMessages { struct FoundMessages {
vector<FullMessageId> full_message_ids; vector<FullMessageId> full_message_ids;

View File

@ -1398,14 +1398,15 @@ class SearchChatMessagesRequest : public RequestActor<> {
int32 offset_; int32 offset_;
int32 limit_; int32 limit_;
MessageSearchFilter filter_; MessageSearchFilter filter_;
MessageId top_thread_message_id_;
int64 random_id_; int64 random_id_;
std::pair<int32, vector<MessageId>> messages_; std::pair<int32, vector<MessageId>> messages_;
void do_run(Promise<Unit> &&promise) override { void do_run(Promise<Unit> &&promise) override {
messages_ = td->messages_manager_->search_dialog_messages(dialog_id_, query_, sender_user_id_, from_message_id_, messages_ = td->messages_manager_->search_dialog_messages(dialog_id_, query_, sender_user_id_, from_message_id_,
offset_, limit_, filter_, random_id_, get_tries() == 3, offset_, limit_, filter_, top_thread_message_id_,
std::move(promise)); random_id_, get_tries() == 3, std::move(promise));
} }
void do_send_result() override { void do_send_result() override {
@ -1424,7 +1425,7 @@ class SearchChatMessagesRequest : public RequestActor<> {
public: public:
SearchChatMessagesRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string query, int32 user_id, SearchChatMessagesRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string query, int32 user_id,
int64 from_message_id, int32 offset, int32 limit, int64 from_message_id, int32 offset, int32 limit,
tl_object_ptr<td_api::SearchMessagesFilter> filter) tl_object_ptr<td_api::SearchMessagesFilter> filter, int64 message_thread_id)
: RequestActor(std::move(td), request_id) : RequestActor(std::move(td), request_id)
, dialog_id_(dialog_id) , dialog_id_(dialog_id)
, query_(std::move(query)) , query_(std::move(query))
@ -1433,6 +1434,7 @@ class SearchChatMessagesRequest : public RequestActor<> {
, offset_(offset) , offset_(offset)
, limit_(limit) , limit_(limit)
, filter_(get_message_search_filter(filter)) , filter_(get_message_search_filter(filter))
, top_thread_message_id_(message_thread_id)
, random_id_(0) { , random_id_(0) {
set_tries(3); set_tries(3);
} }
@ -5459,7 +5461,8 @@ void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CLEAN_INPUT_STRING(request.query_); CLEAN_INPUT_STRING(request.query_);
CREATE_REQUEST(SearchChatMessagesRequest, request.chat_id_, std::move(request.query_), request.sender_user_id_, CREATE_REQUEST(SearchChatMessagesRequest, request.chat_id_, std::move(request.query_), request.sender_user_id_,
request.from_message_id_, request.offset_, request.limit_, std::move(request.filter_)); request.from_message_id_, request.offset_, request.limit_, std::move(request.filter_),
request.message_thread_id_);
} }
void Td::on_request(uint64 id, td_api::searchSecretMessages &request) { void Td::on_request(uint64 id, td_api::searchSecretMessages &request) {

View File

@ -319,7 +319,7 @@ class CliClient final : public Actor {
LOG(ERROR) << (last_message_id >> 20); LOG(ERROR) << (last_message_id >> 20);
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
search_chat_id_, "", 0, last_message_id, 0, 100, search_chat_id_, "", 0, last_message_id, 0, 100,
td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>())); td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>(), 0));
} else { } else {
search_chat_id_ = 0; search_chat_id_ = 0;
} }
@ -1864,7 +1864,7 @@ class CliClient final : public Actor {
search_chat_id_ = as_chat_id(args); search_chat_id_ = as_chat_id(args);
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
search_chat_id_, "", 0, 0, 0, 100, td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>())); search_chat_id_, "", 0, 0, 0, 100, td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>(), 0));
} else if (op == "Search" || op == "SearchA" || op == "SearchM") { } else if (op == "Search" || op == "SearchA" || op == "SearchM") {
string from_date; string from_date;
string limit; string limit;
@ -1899,7 +1899,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), query, 0, 0, 0, send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), query, 0, 0, 0,
to_integer<int32>(limit), nullptr)); to_integer<int32>(limit), nullptr, 0));
} else if (op == "SMME") { } else if (op == "SMME") {
string chat_id; string chat_id;
string limit; string limit;
@ -1910,7 +1910,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", my_id_, 0, 0, send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", my_id_, 0, 0,
to_integer<int32>(limit), nullptr)); to_integer<int32>(limit), nullptr, 0));
} else if (op == "SMU") { } else if (op == "SMU") {
string chat_id; string chat_id;
string user_id; string user_id;
@ -1923,7 +1923,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", as_user_id(user_id), 0, 0, send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", as_user_id(user_id), 0, 0,
to_integer<int32>(limit), nullptr)); to_integer<int32>(limit), nullptr, 0));
} else if (op == "SM") { } else if (op == "SM") {
string chat_id; string chat_id;
string filter; string filter;
@ -1947,7 +1947,7 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), "", 0, as_message_id(offset_message_id), to_integer<int32>(offset), as_chat_id(chat_id), "", 0, as_message_id(offset_message_id), to_integer<int32>(offset),
to_integer<int32>(limit), as_search_messages_filter(filter))); to_integer<int32>(limit), as_search_messages_filter(filter), 0));
} else if (op == "SC") { } else if (op == "SC") {
string limit; string limit;
string offset_message_id; string offset_message_id;
@ -1992,7 +1992,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit), as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterAudio>())); td_api::make_object<td_api::searchMessagesFilterAudio>(), 0));
} else if (op == "SearchDocument") { } else if (op == "SearchDocument") {
string chat_id; string chat_id;
string offset_message_id; string offset_message_id;
@ -2010,7 +2010,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, to_integer<int64>(offset_message_id), 0, to_integer<int32>(limit), as_chat_id(chat_id), query, 0, to_integer<int64>(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterDocument>())); td_api::make_object<td_api::searchMessagesFilterDocument>(), 0));
} else if (op == "SearchPhoto") { } else if (op == "SearchPhoto") {
string chat_id; string chat_id;
string offset_message_id; string offset_message_id;
@ -2028,7 +2028,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit), as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterPhoto>())); td_api::make_object<td_api::searchMessagesFilterPhoto>(), 0));
} else if (op == "SearchChatPhoto") { } else if (op == "SearchChatPhoto") {
string chat_id; string chat_id;
string offset_message_id; string offset_message_id;
@ -2046,7 +2046,7 @@ class CliClient final : public Actor {
} }
send_request(td_api::make_object<td_api::searchChatMessages>( send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit), as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterChatPhoto>())); td_api::make_object<td_api::searchMessagesFilterChatPhoto>(), 0));
} else if (op == "gcmc") { } else if (op == "gcmc") {
string chat_id; string chat_id;
string filter; string filter;