Add getChatMessagePosition.

This commit is contained in:
levlam 2022-09-30 20:04:21 +03:00
parent 481a69676d
commit 1f7258f697
6 changed files with 165 additions and 0 deletions

View File

@ -4995,6 +4995,12 @@ getChatMessageCalendar chat_id:int53 filter:SearchMessagesFilter from_message_id
//@description Returns approximate number of messages of the specified type in the chat @chat_id Identifier of the chat in which to count messages @filter Filter for message content; searchMessagesFilterEmpty is unsupported in this function @return_local Pass true to get the number of messages without sending network requests, or -1 if the number of messages is unknown locally
getChatMessageCount chat_id:int53 filter:SearchMessagesFilter return_local:Bool = Count;
//@description Returns approximate 1-based position of a message among messages, which can be found by the specified filter in the chat. Cannot be used in secret chats
//@chat_id Identifier of the chat in which to find message position @message_id Message identifier
//@filter Filter for message content; searchMessagesFilterEmpty, searchMessagesFilterUnreadMention, searchMessagesFilterUnreadReaction, and searchMessagesFilterFailedToSend are unsupported in this function
//@message_thread_id If not 0, only messages in the specified thread will be considered; supergroups only
getChatMessagePosition chat_id:int53 message_id:int53 filter:SearchMessagesFilter message_thread_id:int53 = Count;
//@description Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id) @chat_id Chat identifier
getChatScheduledMessages chat_id:int53 = Messages;

View File

@ -2354,6 +2354,8 @@ class GetSearchResultCalendarQuery final : public Td::ResultHandler {
td_->contacts_manager_->on_get_users(std::move(result->users_), "GetSearchResultCalendarQuery");
td_->contacts_manager_->on_get_chats(std::move(result->chats_), "GetSearchResultCalendarQuery");
// unused: inexact:flags.0?true min_date:int min_msg_id:int offset_id_offset:flags.1?int
MessagesManager::MessagesInfo info;
info.messages = std::move(result->messages_);
info.total_count = result->count_;
@ -2383,6 +2385,90 @@ class GetSearchResultCalendarQuery final : public Td::ResultHandler {
}
};
class GetMessagePositionQuery final : public Td::ResultHandler {
Promise<int32> promise_;
DialogId dialog_id_;
MessageId message_id_;
MessageSearchFilter filter_;
public:
explicit GetMessagePositionQuery(Promise<int32> &&promise) : promise_(std::move(promise)) {
}
void send(DialogId dialog_id, MessageId message_id, MessageSearchFilter filter, MessageId top_thread_message_id) {
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
CHECK(input_peer != nullptr);
dialog_id_ = dialog_id;
message_id_ = message_id;
filter_ = filter;
int32 flags = 0;
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(
flags, std::move(input_peer), string(), nullptr, top_thread_message_id.get_server_message_id().get(),
get_input_messages_filter(filter), 0, std::numeric_limits<int32>::max(),
message_id.get_server_message_id().get(), -1, 1, std::numeric_limits<int32>::max(), 0, 0)));
}
void on_result(BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::messages_search>(packet);
if (result_ptr.is_error()) {
return on_error(result_ptr.move_as_error());
}
auto messages_ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for GetMessagePositionQuery: " << to_string(messages_ptr);
switch (messages_ptr->get_id()) {
case telegram_api::messages_messages::ID: {
auto messages = move_tl_object_as<telegram_api::messages_messages>(messages_ptr);
if (messages->messages_.size() != 1 ||
MessagesManager::get_message_id(messages->messages_[0], false) != message_id_) {
return promise_.set_error(Status::Error(400, "Message not found by the filter"));
}
return promise_.set_value(narrow_cast<int32>(messages->messages_.size()));
}
case telegram_api::messages_messagesSlice::ID: {
auto messages = move_tl_object_as<telegram_api::messages_messagesSlice>(messages_ptr);
if (messages->messages_.size() != 1 ||
MessagesManager::get_message_id(messages->messages_[0], false) != message_id_) {
return promise_.set_error(Status::Error(400, "Message not found by the filter"));
}
if (messages->offset_id_offset_ <= 0) {
LOG(ERROR) << "Failed to receive position for " << message_id_ << " in " << dialog_id_ << " by " << filter_;
return promise_.set_error(Status::Error(400, "Message position is unknown"));
}
return promise_.set_value(std::move(messages->offset_id_offset_));
}
case telegram_api::messages_channelMessages::ID: {
auto messages = move_tl_object_as<telegram_api::messages_channelMessages>(messages_ptr);
if (messages->messages_.size() != 1 ||
MessagesManager::get_message_id(messages->messages_[0], false) != message_id_) {
return promise_.set_error(Status::Error(400, "Message not found by the filter"));
}
if (messages->offset_id_offset_ <= 0) {
LOG(ERROR) << "Failed to receive position for " << message_id_ << " in " << dialog_id_ << " by " << filter_;
return promise_.set_error(Status::Error(500, "Message position is unknown"));
}
return promise_.set_value(std::move(messages->offset_id_offset_));
}
case telegram_api::messages_messagesNotModified::ID:
LOG(ERROR) << "Server returned messagesNotModified in response to GetMessagePositionQuery";
return promise_.set_error(Status::Error(500, "Receive invalid response"));
default:
UNREACHABLE();
break;
}
}
void on_error(Status status) final {
td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetMessagePositionQuery");
promise_.set_error(std::move(status));
}
};
class SearchMessagesQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
@ -23881,6 +23967,51 @@ void MessagesManager::get_dialog_message_count_from_server(DialogId dialog_id, M
}
}
void MessagesManager::get_dialog_message_position(FullMessageId full_message_id, MessageSearchFilter filter,
MessageId top_thread_message_id, Promise<int32> &&promise) {
auto dialog_id = full_message_id.get_dialog_id();
Dialog *d = get_dialog_force(dialog_id, "get_dialog_message_position");
if (d == nullptr) {
return promise.set_error(Status::Error(400, "Chat not found"));
}
if (!have_input_peer(dialog_id, AccessRights::Read)) {
return promise.set_error(Status::Error(400, "Can't access the chat"));
}
auto message_id = full_message_id.get_message_id();
const Message *m = get_message_force(d, message_id, "get_dialog_message_position");
if (m == nullptr) {
return promise.set_error(Status::Error(400, "Message not found"));
}
if (!m->message_id.is_valid() || !m->message_id.is_server() ||
(get_message_index_mask(d->dialog_id, m) & message_search_filter_index_mask(filter)) == 0) {
return promise.set_error(Status::Error(400, "Message can't be found in the filter"));
}
if (top_thread_message_id != MessageId()) {
if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) {
return promise.set_error(Status::Error(400, "Invalid message thread identifier specified"));
}
if (dialog_id.get_type() != DialogType::Channel || is_broadcast_channel(dialog_id)) {
return promise.set_error(Status::Error(400, "Can't filter by message thread identifier in the chat"));
}
if (m->top_thread_message_id != top_thread_message_id) {
return promise.set_error(Status::Error(400, "Message doesn't belong to the message thread"));
}
}
if (dialog_id.get_type() == DialogType::SecretChat) {
return promise.set_error(Status::Error(400, "The method can't be used in secret chats"));
}
if (filter == MessageSearchFilter::Empty || filter == MessageSearchFilter::UnreadMention ||
filter == MessageSearchFilter::UnreadReaction || filter == MessageSearchFilter::FailedToSend) {
return promise.set_error(Status::Error(400, "The filter is not supported"));
}
td_->create_handler<GetMessagePositionQuery>(std::move(promise))
->send(dialog_id, message_id, filter, top_thread_message_id);
}
void MessagesManager::preload_newer_messages(const Dialog *d, MessageId max_message_id) {
CHECK(d != nullptr);
CHECK(max_message_id.is_valid());

View File

@ -809,6 +809,9 @@ class MessagesManager final : public Actor {
void get_dialog_message_count(DialogId dialog_id, MessageSearchFilter filter, bool return_local,
Promise<int32> &&promise);
void get_dialog_message_position(FullMessageId full_message_id, MessageSearchFilter filter,
MessageId top_thread_message_id, Promise<int32> &&promise);
vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result,
Promise<Unit> &&promise);

View File

@ -5194,6 +5194,21 @@ void Td::on_request(uint64 id, const td_api::getChatMessageCount &request) {
request.return_local_, std::move(query_promise));
}
void Td::on_request(uint64 id, const td_api::getChatMessagePosition &request) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<int32> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
promise.set_value(make_tl_object<td_api::count>(result.move_as_ok()));
}
});
messages_manager_->get_dialog_message_position({DialogId(request.chat_id_), MessageId(request.message_id_)},
get_message_search_filter(request.filter_),
MessageId(request.message_thread_id_), std::move(query_promise));
}
void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request) {
CHECK_IS_USER();
CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_);

View File

@ -654,6 +654,8 @@ class Td final : public Actor {
void on_request(uint64 id, const td_api::getChatMessageCount &request);
void on_request(uint64 id, const td_api::getChatMessagePosition &request);
void on_request(uint64 id, const td_api::getChatScheduledMessages &request);
void on_request(uint64 id, const td_api::getEmojiReaction &request);

View File

@ -2391,6 +2391,14 @@ class CliClient final : public Actor {
get_args(args, chat_id, filter, return_local);
send_request(
td_api::make_object<td_api::getChatMessageCount>(chat_id, as_search_messages_filter(filter), return_local));
} else if (op == "gcmp") {
ChatId chat_id;
MessageId message_id;
string filter;
string message_thread_id;
get_args(args, chat_id, message_id, filter, message_thread_id);
send_request(td_api::make_object<td_api::getChatMessagePosition>(
chat_id, message_id, as_search_messages_filter(filter), as_message_thread_id(message_thread_id)));
} else if (op == "gup" || op == "gupp") {
UserId user_id;
int32 offset;