Add td_api::getMessageThreadHistory.
GitOrigin-RevId: c5aaa396b1fcdd6704302296e407989ff19be0a0
This commit is contained in:
parent
b2c52ede12
commit
b751acc3ae
@ -156,6 +156,7 @@ function split_file($file, $chunks, $undo) {
|
||||
'(?<name>[A-Z][A-Za-z]*) : public (Td::ResultHandler|NetActor|Request)|'.
|
||||
'(CREATE_REQUEST|CREATE_NO_ARGS_REQUEST)[(](?<name>[A-Z][A-Za-z]*)|'.
|
||||
'(?<name>complete_pending_preauthentication_requests)|'.
|
||||
'(?<name>get_message_history_slice)|'.
|
||||
'(Up|Down)load[a-zA-Z]*C(?<name>allback)|(up|down)load_[a-z_]*_c(?<name>allback)_|'.
|
||||
'(?<name>lazy_to_json)|'.
|
||||
'(?<name>LogEvent)[^sA]|'.
|
||||
|
@ -3624,10 +3624,19 @@ getGroupsInCommon user_id:int32 offset_chat_id:int53 limit:int32 = Chats;
|
||||
//@chat_id Chat identifier
|
||||
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
|
||||
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset up to 99 to get additionally 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 or equal to -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 or equal to -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
|
||||
//@only_local If true, returns only messages that are available locally without sending network requests
|
||||
getChatHistory chat_id:int53 from_message_id:int53 offset:int32 limit:int32 only_local:Bool = Messages;
|
||||
|
||||
//@description Returns messages in a message thread of a message. Can be used only if message.can_get_message_thread == true. Message thread of a channel message is in the channel's linked supergroup.
|
||||
//-The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id). For optimal performance the number of returned messages is chosen by the library
|
||||
//@chat_id Chat identifier
|
||||
//@message_id Message identifier, which thread history needs to be returned
|
||||
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
|
||||
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset up to 99 to get additionally 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 or equal to -offset. Fewer messages may be returned than specified by the limit, even if the end of the message thread history has not been reached
|
||||
getMessageThreadHistory chat_id:int53 message_id:int53 from_message_id:int53 offset:int32 limit:int32 = Messages;
|
||||
|
||||
//@description Deletes all messages in the chat. Use Chat.can_be_deleted_only_for_self and Chat.can_be_deleted_for_all_users fields to find whether and how the method can be applied to the chat
|
||||
//@chat_id Chat identifier @remove_from_chat_list Pass true if the chat should be removed from the chat list @revoke Pass true to try to delete chat history for all users
|
||||
deleteChatHistory chat_id:int53 remove_from_chat_list:Bool revoke:Bool = Ok;
|
||||
|
Binary file not shown.
@ -19330,7 +19330,7 @@ tl_object_ptr<td_api::messages> MessagesManager::get_dialog_history(DialogId dia
|
||||
return nullptr;
|
||||
}
|
||||
if (offset < -limit) {
|
||||
promise.set_error(Status::Error(5, "Parameter offset must not be less than -limit"));
|
||||
promise.set_error(Status::Error(5, "Parameter offset must be greater than or equal to -limit"));
|
||||
return nullptr;
|
||||
}
|
||||
bool is_limit_increased = false;
|
||||
@ -19728,6 +19728,202 @@ void MessagesManager::on_read_history_finished(DialogId dialog_id, MessageId top
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class It>
|
||||
vector<MessageId> MessagesManager::get_message_history_slice(const T &begin, It it, const T &end,
|
||||
MessageId from_message_id, int32 offset, int32 limit) {
|
||||
int32 left_offset = -offset;
|
||||
int32 left_limit = limit + offset;
|
||||
while (left_offset > 0 && it != end) {
|
||||
++it;
|
||||
left_offset--;
|
||||
left_limit++;
|
||||
}
|
||||
|
||||
vector<MessageId> message_ids;
|
||||
while (left_limit > 0 && it != begin) {
|
||||
--it;
|
||||
left_limit--;
|
||||
message_ids.push_back(*it);
|
||||
}
|
||||
return message_ids;
|
||||
}
|
||||
|
||||
std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_history(
|
||||
DialogId dialog_id, MessageId message_id, MessageId from_message_id, int32 offset, int32 limit, int64 &random_id,
|
||||
Promise<Unit> &&promise) {
|
||||
if (limit <= 0) {
|
||||
promise.set_error(Status::Error(3, "Parameter limit must be positive"));
|
||||
return {};
|
||||
}
|
||||
if (limit > MAX_GET_HISTORY) {
|
||||
limit = MAX_GET_HISTORY;
|
||||
}
|
||||
if (offset > 0) {
|
||||
promise.set_error(Status::Error(5, "Parameter offset must be non-positive"));
|
||||
return {};
|
||||
}
|
||||
if (offset <= -MAX_GET_HISTORY) {
|
||||
promise.set_error(Status::Error(5, "Parameter offset must be greater than -100"));
|
||||
return {};
|
||||
}
|
||||
if (offset < -limit) {
|
||||
promise.set_error(Status::Error(5, "Parameter offset must be greater than or equal to -limit"));
|
||||
return {};
|
||||
}
|
||||
bool is_limit_increased = false;
|
||||
if (limit == -offset) {
|
||||
limit++;
|
||||
is_limit_increased = true;
|
||||
}
|
||||
CHECK(0 < limit && limit <= MAX_GET_HISTORY);
|
||||
CHECK(-limit < offset && offset <= 0);
|
||||
|
||||
Dialog *d = get_dialog_force(dialog_id);
|
||||
if (d == nullptr) {
|
||||
promise.set_error(Status::Error(6, "Chat not found"));
|
||||
return {};
|
||||
}
|
||||
if (!have_input_peer(dialog_id, AccessRights::Read)) {
|
||||
promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||
return {};
|
||||
}
|
||||
if (dialog_id.get_type() != DialogType::Channel) {
|
||||
promise.set_error(Status::Error(400, "Can't get message thread history in the chat"));
|
||||
return {};
|
||||
}
|
||||
|
||||
if (from_message_id == MessageId() || from_message_id.get() > MessageId::max().get()) {
|
||||
from_message_id = MessageId::max();
|
||||
}
|
||||
if (!from_message_id.is_valid()) {
|
||||
promise.set_error(Status::Error(3, "Parameter from_message_id must be identifier of the chat message or 0"));
|
||||
return {};
|
||||
}
|
||||
|
||||
DialogId message_thread_dialog_id;
|
||||
MessageId top_thread_message_id;
|
||||
{
|
||||
Message *m = get_message_force(d, message_id, "get_message_thread_history 1");
|
||||
if (m == nullptr) {
|
||||
promise.set_error(Status::Error(400, "Message not found"));
|
||||
return {};
|
||||
}
|
||||
|
||||
if (m->reply_info.is_comment) {
|
||||
if (!is_active_message_reply_info(dialog_id, m->reply_info)) {
|
||||
promise.set_error(Status::Error(400, "Message has no comments"));
|
||||
return {};
|
||||
}
|
||||
if (!m->linked_top_thread_message_id.is_valid()) {
|
||||
get_message_thread(
|
||||
dialog_id, message_id,
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<MessageThreadInfo> &&result) mutable {
|
||||
if (result.is_error()) {
|
||||
promise.set_error(result.move_as_error());
|
||||
} else {
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
}));
|
||||
return {};
|
||||
}
|
||||
message_thread_dialog_id = DialogId(m->reply_info.channel_id);
|
||||
top_thread_message_id = m->linked_top_thread_message_id;
|
||||
} else {
|
||||
if (!m->top_thread_message_id.is_valid()) {
|
||||
promise.set_error(Status::Error(400, "Message has no thread"));
|
||||
return {};
|
||||
}
|
||||
message_thread_dialog_id = dialog_id;
|
||||
top_thread_message_id = m->top_thread_message_id;
|
||||
}
|
||||
}
|
||||
CHECK(top_thread_message_id.is_valid());
|
||||
|
||||
if (random_id != 0) {
|
||||
// request has already been sent before
|
||||
auto it = found_dialog_messages_.find(random_id);
|
||||
CHECK(it != found_dialog_messages_.end());
|
||||
auto result = std::move(it->second.second);
|
||||
found_dialog_messages_.erase(it);
|
||||
|
||||
auto dialog_id_it = found_dialog_messages_dialog_id_.find(random_id);
|
||||
if (dialog_id_it != found_dialog_messages_dialog_id_.end()) {
|
||||
dialog_id = dialog_id_it->second;
|
||||
found_dialog_messages_dialog_id_.erase(dialog_id_it);
|
||||
|
||||
d = get_dialog(dialog_id);
|
||||
CHECK(d != nullptr);
|
||||
}
|
||||
if (dialog_id != message_thread_dialog_id) {
|
||||
promise.set_error(Status::Error(500, "Receive messages in an unexpected chat"));
|
||||
return {};
|
||||
}
|
||||
|
||||
auto yet_unsent_it = d->yet_unsent_thread_message_ids.find(top_thread_message_id);
|
||||
if (yet_unsent_it != d->yet_unsent_thread_message_ids.end()) {
|
||||
const std::set<MessageId> &message_ids = yet_unsent_it->second;
|
||||
auto merge_message_ids = get_message_history_slice(message_ids.begin(), message_ids.lower_bound(from_message_id),
|
||||
message_ids.end(), from_message_id, offset, limit);
|
||||
vector<MessageId> new_result(result.size() + merge_message_ids.size());
|
||||
std::merge(result.begin(), result.end(), merge_message_ids.begin(), merge_message_ids.end(), new_result.begin(),
|
||||
std::greater<>());
|
||||
result = std::move(new_result);
|
||||
}
|
||||
|
||||
Message *top_m = get_message_force(d, top_thread_message_id, "get_message_thread_history 2");
|
||||
if (top_m != nullptr && !top_m->local_thread_message_ids.empty()) {
|
||||
vector<MessageId> &message_ids = top_m->local_thread_message_ids;
|
||||
vector<MessageId> merge_message_ids;
|
||||
while (true) {
|
||||
merge_message_ids = get_message_history_slice(
|
||||
message_ids.begin(), std::lower_bound(message_ids.begin(), message_ids.end(), from_message_id),
|
||||
message_ids.end(), from_message_id, offset, limit);
|
||||
bool found_deleted = false;
|
||||
for (auto local_message_id : merge_message_ids) {
|
||||
Message *local_m = get_message_force(d, local_message_id, "get_message_thread_history 3");
|
||||
if (local_m == nullptr) {
|
||||
auto local_it = std::lower_bound(message_ids.begin(), message_ids.end(), local_message_id);
|
||||
CHECK(local_it != message_ids.end() && *local_it == local_message_id);
|
||||
message_ids.erase(local_it);
|
||||
found_deleted = true;
|
||||
}
|
||||
}
|
||||
if (!found_deleted) {
|
||||
break;
|
||||
}
|
||||
on_message_changed(d, top_m, false, "get_message_thread_history");
|
||||
}
|
||||
vector<MessageId> new_result(result.size() + merge_message_ids.size());
|
||||
std::merge(result.begin(), result.end(), merge_message_ids.begin(), merge_message_ids.end(), new_result.begin(),
|
||||
std::greater<>());
|
||||
result = std::move(new_result);
|
||||
}
|
||||
|
||||
if (is_limit_increased) {
|
||||
limit--;
|
||||
}
|
||||
|
||||
std::reverse(result.begin(), result.end());
|
||||
result = get_message_history_slice(result.begin(), std::lower_bound(result.begin(), result.end(), from_message_id),
|
||||
result.end(), from_message_id, offset, limit);
|
||||
|
||||
LOG(INFO) << "Return " << result.size() << " messages in result to getMessageThreadHistory";
|
||||
|
||||
promise.set_value(Unit());
|
||||
return {dialog_id, std::move(result)};
|
||||
}
|
||||
|
||||
do {
|
||||
random_id = Random::secure_int64();
|
||||
} while (random_id == 0 || found_dialog_messages_.find(random_id) != found_dialog_messages_.end());
|
||||
found_dialog_messages_[random_id]; // reserve place for result
|
||||
|
||||
td_->create_handler<SearchMessagesQuery>(std::move(promise))
|
||||
->send(dialog_id, string(), UserId(), nullptr, from_message_id.get_next_server_message_id(), offset, limit,
|
||||
MessageSearchFilter::Empty, message_id, random_id);
|
||||
return {};
|
||||
}
|
||||
|
||||
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,
|
||||
int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 &random_id, bool use_db,
|
||||
|
@ -701,6 +701,11 @@ class MessagesManager : public Actor {
|
||||
int32 limit, int left_tries, bool only_local,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
std::pair<DialogId, vector<MessageId>> get_message_thread_history(DialogId dialog_id, MessageId message_id,
|
||||
MessageId from_message_id, int32 offset,
|
||||
int32 limit, int64 &random_id,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
|
||||
UserId sender_user_id, MessageId from_message_id,
|
||||
int32 offset, int32 limit, MessageSearchFilter filter,
|
||||
@ -1987,6 +1992,10 @@ class MessagesManager : public Actor {
|
||||
|
||||
void on_update_dialog_online_member_count_timeout(DialogId dialog_id);
|
||||
|
||||
template <class T, class It>
|
||||
vector<MessageId> get_message_history_slice(const T &begin, It it, const T &end, MessageId from_message_id,
|
||||
int32 offset, int32 limit);
|
||||
|
||||
void preload_newer_messages(const Dialog *d, MessageId max_message_id);
|
||||
|
||||
void preload_older_messages(const Dialog *d, MessageId min_message_id);
|
||||
|
@ -1398,6 +1398,39 @@ class GetChatHistoryRequest : public RequestActor<> {
|
||||
}
|
||||
};
|
||||
|
||||
class GetMessageThreadHistoryRequest : public RequestActor<> {
|
||||
DialogId dialog_id_;
|
||||
MessageId message_id_;
|
||||
MessageId from_message_id_;
|
||||
int32 offset_;
|
||||
int32 limit_;
|
||||
int64 random_id_;
|
||||
|
||||
std::pair<DialogId, vector<MessageId>> messages_;
|
||||
|
||||
void do_run(Promise<Unit> &&promise) override {
|
||||
messages_ = td->messages_manager_->get_message_thread_history(dialog_id_, message_id_, from_message_id_, offset_,
|
||||
limit_, random_id_, std::move(promise));
|
||||
}
|
||||
|
||||
void do_send_result() override {
|
||||
send_result(td->messages_manager_->get_messages_object(-1, messages_.first, messages_.second));
|
||||
}
|
||||
|
||||
public:
|
||||
GetMessageThreadHistoryRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
|
||||
int64 from_message_id, int32 offset, int32 limit)
|
||||
: RequestActor(std::move(td), request_id)
|
||||
, dialog_id_(dialog_id)
|
||||
, message_id_(message_id)
|
||||
, from_message_id_(from_message_id)
|
||||
, offset_(offset)
|
||||
, limit_(limit)
|
||||
, random_id_(0) {
|
||||
set_tries(3);
|
||||
}
|
||||
};
|
||||
|
||||
class SearchChatMessagesRequest : public RequestActor<> {
|
||||
DialogId dialog_id_;
|
||||
string query_;
|
||||
@ -5488,6 +5521,12 @@ void Td::on_request(uint64 id, const td_api::deleteChatHistory &request) {
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getMessageThreadHistory &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST(GetMessageThreadHistoryRequest, request.chat_id_, request.message_id_, request.from_message_id_,
|
||||
request.offset_, request.limit_);
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.query_);
|
||||
|
@ -572,6 +572,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, const td_api::deleteChatHistory &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getMessageThreadHistory &request);
|
||||
|
||||
void on_request(uint64 id, td_api::searchChatMessages &request);
|
||||
|
||||
void on_request(uint64 id, td_api::searchSecretMessages &request);
|
||||
|
@ -1816,13 +1816,17 @@ class CliClient final : public Actor {
|
||||
}
|
||||
send_request(td_api::make_object<td_api::getGroupsInCommon>(as_user_id(user_id), as_chat_id(offset_chat_id),
|
||||
to_integer<int32>(limit)));
|
||||
} else if (op == "gh" || op == "GetHistory" || op == "ghl") {
|
||||
} else if (op == "gh" || op == "GetHistory" || op == "ghl" || op == "gmth") {
|
||||
string chat_id;
|
||||
string thread_message_id;
|
||||
string from_message_id;
|
||||
string offset;
|
||||
string limit;
|
||||
|
||||
std::tie(chat_id, args) = split(args);
|
||||
if (op == "gmth") {
|
||||
std::tie(thread_message_id, args) = split(args);
|
||||
}
|
||||
std::tie(from_message_id, args) = split(args);
|
||||
if (from_message_id.empty()) {
|
||||
from_message_id = "0";
|
||||
@ -1837,6 +1841,10 @@ class CliClient final : public Actor {
|
||||
}
|
||||
if (!args.empty()) {
|
||||
LOG(ERROR) << "Wrong parameters to function getChatHistory specified";
|
||||
} else if (op == "gmth") {
|
||||
send_request(td_api::make_object<td_api::getMessageThreadHistory>(
|
||||
as_chat_id(chat_id), as_message_id(thread_message_id), as_message_id(from_message_id),
|
||||
to_integer<int32>(offset), to_integer<int32>(limit)));
|
||||
} else {
|
||||
send_request(td_api::make_object<td_api::getChatHistory>(as_chat_id(chat_id), as_message_id(from_message_id),
|
||||
to_integer<int32>(offset), to_integer<int32>(limit),
|
||||
|
Loading…
x
Reference in New Issue
Block a user