Add td_api::getChatMessageCalendar.

This commit is contained in:
levlam 2021-10-30 03:34:49 +03:00
parent 39b5db357e
commit 13c76b349d
6 changed files with 288 additions and 3 deletions

View File

@ -819,6 +819,12 @@ messagePosition position:int32 message_id:int53 date:int32 = MessagePosition;
//@description Contains a list of message positions @total_count Total count of messages found @positions List of message positions
messagePositions total_count:int32 positions:vector<messagePosition> = MessagePositions;
//@description Contains information about found messages sent in a specific day @total_count Total number of found messages sent in the day @message First message sent in the day
messageCalendarDay total_count:int32 message:message = MessageCalendarDay;
//@description Contains information about found messages, splitted by days @total_count Total number of found messages @utc_time_offset UTC time offset in seconds, used to split messages by days @days Information about messages sent
messageCalendar total_count:int32 utc_time_offset:int32 days:vector<messageCalendarDay> = MessageCalendar;
//@description Describes a sponsored message @id Unique sponsored message identifier @sponsor_chat_id Chat identifier
//@link An internal link to be opened when the sponsored message is clicked; may be null. If null, the sponsor chat needs to be opened instead @content Content of the message
@ -4299,6 +4305,12 @@ getChatMessageByDate chat_id:int53 date:int32 = Message;
//@limit The expected number of message positions to be returned. A smaller number of positions can be returned, if there are not enough appropriate messages
getChatSparseMessagePositions chat_id:int53 filter:SearchMessagesFilter from_message_id:int53 limit:int32 = MessagePositions;
//@description Returns information about the next messages of the specified type in the chat splitted by days. Returns the results in reverse chronological order. Can return partial result for the last returned day
//@chat_id Identifier of the chat in which to return information about messages
//@filter Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterCall, searchMessagesFilterMissedCall, searchMessagesFilterMention, searchMessagesFilterUnreadMention and searchMessagesFilterFailedToSend are unsupported in this function
//@from_message_id The message identifier from which to return information about messages; use 0 to get results from the last message
getChatMessageCalendar chat_id:int53 filter:SearchMessagesFilter from_message_id:int53 = MessageCalendar;
//@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 If true, returns count that is available locally without sending network requests, returning -1 if the number of messages is unknown
getChatMessageCount chat_id:int53 filter:SearchMessagesFilter return_local:Bool = Count;

View File

@ -2167,6 +2167,70 @@ class ReadDiscussionQuery final : public Td::ResultHandler {
}
};
class GetSearchResultCalendarQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
MessageId from_message_id_;
MessageSearchFilter filter_;
int64 random_id_;
public:
explicit GetSearchResultCalendarQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(DialogId dialog_id, MessageId from_message_id, MessageSearchFilter filter, int64 random_id) {
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
CHECK(input_peer != nullptr);
dialog_id_ = dialog_id;
from_message_id_ = from_message_id;
filter_ = filter;
random_id_ = random_id;
send_query(G()->net_query_creator().create(telegram_api::messages_getSearchResultsCalendar(
std::move(input_peer), get_input_messages_filter(filter), from_message_id.get_server_message_id().get(), 0)));
}
void on_result(uint64 id, BufferSlice packet) final {
auto result_ptr = fetch_result<telegram_api::messages_getSearchResultsCalendar>(packet);
if (result_ptr.is_error()) {
return on_error(id, result_ptr.move_as_error());
}
auto result = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for GetSearchResultCalendarQuery: " << to_string(result);
td->contacts_manager_->on_get_users(std::move(result->users_), "GetSearchResultCalendarQuery");
td->contacts_manager_->on_get_chats(std::move(result->chats_), "GetSearchResultCalendarQuery");
MessagesManager::MessagesInfo info;
info.messages = std::move(result->messages_);
info.total_count = result->count_;
info.is_channel_messages = dialog_id_.get_type() == DialogType::Channel;
td->messages_manager_->get_channel_difference_if_needed(
dialog_id_, std::move(info),
PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_,
from_message_id = from_message_id_, filter = filter_, random_id = random_id_,
periods = std::move(result->periods_),
promise = std::move(promise_)](Result<MessagesManager::MessagesInfo> &&result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
auto info = result.move_as_ok();
send_closure(actor_id, &MessagesManager::on_get_message_search_result_calendar, dialog_id, from_message_id,
filter, random_id, info.total_count, std::move(info.messages), std::move(periods),
std::move(promise));
}
}));
}
void on_error(uint64 id, Status status) final {
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SearchMessagesQuery");
td->messages_manager_->on_failed_get_message_search_result_calendar(dialog_id_, random_id_);
promise_.set_error(std::move(status));
}
};
class SearchMessagesQuery final : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
@ -9693,6 +9757,71 @@ void MessagesManager::on_failed_public_dialogs_search(const string &query, Statu
}
}
void MessagesManager::on_get_message_search_result_calendar(
DialogId dialog_id, MessageId from_message_id, MessageSearchFilter filter, int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages,
vector<tl_object_ptr<telegram_api::searchResultsCalendarPeriod>> &&periods, Promise<Unit> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
auto it = found_dialog_message_calendars_.find(random_id);
CHECK(it != found_dialog_message_calendars_.end());
int32 received_message_count = 0;
for (auto &message : messages) {
auto new_full_message_id = on_get_message(std::move(message), false, dialog_id.get_type() == DialogType::Channel,
false, false, false, "on_get_message_search_result_calendar");
if (new_full_message_id == FullMessageId()) {
total_count--;
continue;
}
if (new_full_message_id.get_dialog_id() != dialog_id) {
LOG(ERROR) << "Receive " << new_full_message_id << " instead of a message in " << dialog_id;
total_count--;
continue;
}
received_message_count++;
}
if (total_count < received_message_count) {
LOG(ERROR) << "Receive " << received_message_count << " valid messages out of " << total_count << " in "
<< messages.size() << " messages";
total_count = received_message_count;
}
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
auto &old_message_count = d->message_count_by_index[message_search_filter_index(filter)];
if (old_message_count != total_count) {
old_message_count = total_count;
on_dialog_updated(dialog_id, "on_get_message_search_result_calendar");
}
vector<td_api::object_ptr<td_api::messageCalendarDay>> days;
for (auto &period : periods) {
auto message_id = MessageId(ServerMessageId(period->min_msg_id_));
const auto *m = get_message(d, message_id);
if (m == nullptr) {
LOG(ERROR) << "Failed to find " << message_id;
continue;
}
if (period->count_ <= 0) {
LOG(ERROR) << "Receive " << to_string(period);
continue;
}
days.push_back(td_api::make_object<td_api::messageCalendarDay>(
period->count_, get_message_object(dialog_id, m, "on_get_message_search_result_calendar")));
}
it->second = td_api::make_object<td_api::messageCalendar>(total_count, Clocks::tz_offset(), std::move(days));
promise.set_value(Unit());
}
void MessagesManager::on_failed_get_message_search_result_calendar(DialogId dialog_id, int64 random_id) {
auto it = found_dialog_message_calendars_.find(random_id);
CHECK(it != found_dialog_message_calendars_.end());
found_dialog_message_calendars_.erase(it);
}
void MessagesManager::on_get_dialog_messages_search_result(
DialogId dialog_id, const string &query, DialogId sender_dialog_id, MessageId from_message_id, int32 offset,
int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 random_id, int32 total_count,
@ -21220,7 +21349,7 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
from_message_id = MessageId::max();
}
if (!from_message_id.is_valid()) {
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of the chat message or 0"));
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of a chat message or 0"));
return {};
}
@ -21339,6 +21468,95 @@ std::pair<DialogId, vector<MessageId>> MessagesManager::get_message_thread_histo
return {};
}
td_api::object_ptr<td_api::messageCalendar> MessagesManager::get_dialog_message_calendar(DialogId dialog_id,
MessageId from_message_id,
MessageSearchFilter filter,
int64 &random_id, bool use_db,
Promise<Unit> &&promise) {
if (random_id != 0) {
// request has already been sent before
auto it = found_dialog_message_calendars_.find(random_id);
if (it != found_dialog_message_calendars_.end()) {
auto result = std::move(it->second);
found_dialog_message_calendars_.erase(it);
promise.set_value(Unit());
return result;
}
random_id = 0;
}
LOG(INFO) << "Get message calendar in " << dialog_id << " filtered by " << filter << " from " << from_message_id;
if (from_message_id.get() > MessageId::max().get()) {
from_message_id = MessageId::max();
}
if (!from_message_id.is_valid() && from_message_id != MessageId()) {
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of a chat message or 0"));
return {};
}
from_message_id = from_message_id.get_next_server_message_id();
const Dialog *d = get_dialog_force(dialog_id, "get_dialog_message_calendar");
if (d == nullptr) {
promise.set_error(Status::Error(400, "Chat not found"));
return {};
}
if (!have_input_peer(dialog_id, AccessRights::Read)) {
promise.set_error(Status::Error(400, "Can't access the chat"));
return {};
}
do {
random_id = Random::secure_int64();
} while (random_id == 0 || found_dialog_message_calendars_.find(random_id) != found_dialog_message_calendars_.end());
found_dialog_message_calendars_[random_id]; // reserve place for result
if (filter == MessageSearchFilter::Empty || filter == MessageSearchFilter::Call ||
filter == MessageSearchFilter::MissedCall || filter == MessageSearchFilter::Mention ||
filter == MessageSearchFilter::UnreadMention) {
promise.set_error(Status::Error(400, "The filter is not supported"));
return {};
}
// Trying to use database
if (use_db && G()->parameters().use_message_db) {
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)];
auto fixed_from_message_id = from_message_id;
if (fixed_from_message_id == MessageId()) {
fixed_from_message_id = MessageId::max();
}
LOG(INFO) << "Get message calendar in " << dialog_id << " from " << fixed_from_message_id << ", have up to "
<< first_db_message_id << ", message_count = " << message_count;
if (first_db_message_id < fixed_from_message_id && message_count != -1) {
// TODO
}
}
if (filter == MessageSearchFilter::FailedToSend) {
promise.set_value(Unit());
return {};
}
LOG(DEBUG) << "Get message calendar from server in " << dialog_id << " from " << from_message_id;
switch (dialog_id.get_type()) {
case DialogType::None:
case DialogType::User:
case DialogType::Chat:
case DialogType::Channel:
td_->create_handler<GetSearchResultCalendarQuery>(std::move(promise))
->send(dialog_id, from_message_id, filter, random_id);
break;
case DialogType::SecretChat:
promise.set_value(Unit());
break;
default:
UNREACHABLE();
promise.set_error(Status::Error(500, "Search messages is not supported"));
}
return {};
}
std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
DialogId dialog_id, const string &query, const td_api::object_ptr<td_api::MessageSender> &sender,
MessageId from_message_id, int32 offset, int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id,
@ -21381,7 +21599,7 @@ std::pair<int32, vector<MessageId>> MessagesManager::search_dialog_messages(
}
if (!from_message_id.is_valid() && from_message_id != MessageId()) {
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of the chat message or 0"));
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of a chat message or 0"));
return result;
}
from_message_id = from_message_id.get_next_server_message_id();
@ -21569,7 +21787,7 @@ std::pair<int32, vector<FullMessageId>> MessagesManager::search_call_messages(Me
}
if (!from_message_id.is_valid() && from_message_id != MessageId()) {
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of the chat message or 0"));
promise.set_error(Status::Error(400, "Parameter from_message_id must be identifier of a chat message or 0"));
return result;
}
from_message_id = from_message_id.get_next_server_message_id();

View File

@ -205,6 +205,13 @@ class MessagesManager final : public Actor {
vector<tl_object_ptr<telegram_api::Peer>> &&peers);
void on_failed_public_dialogs_search(const string &query, Status &&error);
void on_get_message_search_result_calendar(DialogId dialog_id, MessageId from_message_id, MessageSearchFilter filter,
int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages,
vector<tl_object_ptr<telegram_api::searchResultsCalendarPeriod>> &&periods,
Promise<Unit> &&promise);
void on_failed_get_message_search_result_calendar(DialogId dialog_id, int64 random_id);
void on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, DialogId sender_dialog_id,
MessageId from_message_id, int32 offset, int32 limit,
MessageSearchFilter filter, MessageId top_thread_message_id,
@ -695,6 +702,10 @@ class MessagesManager final : public Actor {
int32 limit, int64 &random_id,
Promise<Unit> &&promise);
td_api::object_ptr<td_api::messageCalendar> get_dialog_message_calendar(DialogId dialog_id, MessageId from_message_id,
MessageSearchFilter filter, int64 &random_id,
bool use_db, Promise<Unit> &&promise);
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
const td_api::object_ptr<td_api::MessageSender> &sender,
MessageId from_message_id, int32 offset, int32 limit,
@ -3324,6 +3335,7 @@ class MessagesManager final : public Actor {
std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_;
std::unordered_map<int64, td_api::object_ptr<td_api::messageCalendar>> found_dialog_message_calendars_;
std::unordered_map<int64, std::pair<int32, vector<MessageId>>>
found_dialog_messages_; // random_id -> [total_count, [message_id]...]
std::unordered_map<int64, DialogId> found_dialog_messages_dialog_id_; // random_id -> dialog_id

View File

@ -1349,6 +1349,35 @@ class GetMessageThreadHistoryRequest final : public RequestActor<> {
}
};
class GetChatMessageCalendarRequest final : public RequestActor<> {
DialogId dialog_id_;
MessageId from_message_id_;
MessageSearchFilter filter_;
int64 random_id_;
td_api::object_ptr<td_api::messageCalendar> calendar_;
void do_run(Promise<Unit> &&promise) final {
calendar_ = td->messages_manager_->get_dialog_message_calendar(dialog_id_, from_message_id_, filter_, random_id_,
get_tries() == 3, std::move(promise));
}
void do_send_result() final {
send_result(std::move(calendar_));
}
public:
GetChatMessageCalendarRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 from_message_id,
tl_object_ptr<td_api::SearchMessagesFilter> filter)
: RequestActor(std::move(td), request_id)
, dialog_id_(dialog_id)
, from_message_id_(from_message_id)
, filter_(get_message_search_filter(filter))
, random_id_(0) {
set_tries(3);
}
};
class SearchChatMessagesRequest final : public RequestActor<> {
DialogId dialog_id_;
string query_;
@ -5321,6 +5350,11 @@ void Td::on_request(uint64 id, const td_api::getMessageThreadHistory &request) {
request.offset_, request.limit_);
}
void Td::on_request(uint64 id, td_api::getChatMessageCalendar &request) {
CHECK_IS_USER();
CREATE_REQUEST(GetChatMessageCalendarRequest, request.chat_id_, request.from_message_id_, std::move(request.filter_));
}
void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.query_);

View File

@ -612,6 +612,8 @@ class Td final : public Actor {
void on_request(uint64 id, const td_api::getMessageThreadHistory &request);
void on_request(uint64 id, td_api::getChatMessageCalendar &request);
void on_request(uint64 id, td_api::searchChatMessages &request);
void on_request(uint64 id, td_api::searchSecretMessages &request);

View File

@ -2097,6 +2097,13 @@ class CliClient final : public Actor {
string limit;
get_args(args, chat_id, limit);
send_request(td_api::make_object<td_api::searchChatRecentLocationMessages>(as_chat_id(chat_id), as_limit(limit)));
} else if (op == "gcmca") {
string chat_id;
string filter;
string from_message_id;
get_args(args, chat_id, filter, from_message_id);
send_request(td_api::make_object<td_api::getChatMessageCalendar>(
as_chat_id(chat_id), as_search_messages_filter(filter), as_message_id(from_message_id)));
} else if (op == "SearchAudio" || op == "SearchDocument" || op == "SearchPhoto" || op == "SearchChatPhoto") {
string chat_id;
string offset_message_id;