Add MessagesDbDialogCalendarQuery.

This commit is contained in:
levlam 2021-11-01 13:50:45 +03:00
parent 463c4e96ac
commit 5a82af3f7f
5 changed files with 147 additions and 12 deletions

View File

@ -4307,7 +4307,7 @@ getChatSparseMessagePositions chat_id:int53 filter:SearchMessagesFilter from_mes
//@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
//@filter Filter for message content. Filters searchMessagesFilterEmpty, searchMessagesFilterCall, searchMessagesFilterMissedCall, searchMessagesFilterMention and searchMessagesFilterUnreadMention 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;

View File

@ -611,6 +611,38 @@ class MessagesDbImpl final : public MessagesDbSyncInterface {
return std::make_pair(std::move(messages), next_expires_till);
}
Result<MessagesDbCalendar> get_dialog_message_calendar(MessagesDbDialogCalendarQuery query) final {
auto &stmt = get_messages_from_index_stmts_[message_search_filter_index(query.filter)].desc_stmt_;
SCOPE_EXIT {
stmt.reset();
};
int32 limit = 1000;
stmt.bind_int64(1, query.dialog_id.get()).ensure();
stmt.bind_int64(2, query.from_message_id.get()).ensure();
stmt.bind_int32(3, limit).ensure();
vector<MessagesDbDialogMessage> messages;
vector<int32> total_counts;
stmt.step().ensure();
int32 current_day = std::numeric_limits<int32>::max();
while (stmt.has_row()) {
auto data_slice = stmt.view_blob(0);
MessageId message_id(stmt.view_int64(1));
auto info = get_message_info(message_id, data_slice, false);
auto day = (query.tz_offset + info.second) / 86400;
if (day >= current_day) {
CHECK(!total_counts.empty());
total_counts.back()++;
} else {
current_day = day;
messages.push_back(MessagesDbDialogMessage{message_id, BufferSlice(data_slice)});
total_counts.push_back(1);
}
stmt.step().ensure();
}
return MessagesDbCalendar{std::move(messages), std::move(total_counts)};
}
Result<vector<MessagesDbDialogMessage>> get_messages(MessagesDbMessagesQuery query) final {
if (query.filter != MessageSearchFilter::Empty) {
return get_messages_from_index(query.dialog_id, query.from_message_id, query.filter, query.offset, query.limit);
@ -892,7 +924,11 @@ class MessagesDbImpl final : public MessagesDbSyncInterface {
}
static std::pair<MessageId, int32> get_message_info(const MessagesDbDialogMessage &message, bool from_data = false) {
LogEventParser message_date_parser(message.data.as_slice());
return get_message_info(message.message_id, message.data.as_slice(), from_data);
}
static std::pair<MessageId, int32> get_message_info(MessageId message_id, Slice data, bool from_data) {
LogEventParser message_date_parser(data);
int32 flags;
int32 flags2 = 0;
int32 flags3 = 0;
@ -904,17 +940,17 @@ class MessagesDbImpl final : public MessagesDbSyncInterface {
}
}
bool has_sender = (flags & (1 << 10)) != 0;
MessageId message_id;
td::parse(message_id, message_date_parser);
MessageId data_message_id;
td::parse(data_message_id, message_date_parser);
UserId sender_user_id;
if (has_sender) {
td::parse(sender_user_id, message_date_parser);
}
int32 date;
td::parse(date, message_date_parser);
LOG(INFO) << "Loaded " << message.message_id << "(aka " << message_id << ") sent at " << date << " by "
LOG(INFO) << "Loaded " << message_id << "(aka " << data_message_id << ") sent at " << date << " by "
<< sender_user_id;
return {from_data ? message_id : message.message_id, date};
return {from_data ? data_message_id : message_id, date};
}
};
@ -980,6 +1016,10 @@ class MessagesDbAsync final : public MessagesDbAsyncInterface {
std::move(promise));
}
void get_dialog_message_calendar(MessagesDbDialogCalendarQuery query, Promise<MessagesDbCalendar> promise) final {
send_closure_later(impl_, &Impl::get_dialog_message_calendar, std::move(query), std::move(promise));
}
void get_messages(MessagesDbMessagesQuery query, Promise<vector<MessagesDbDialogMessage>> promise) final {
send_closure_later(impl_, &Impl::get_messages, std::move(query), std::move(promise));
}
@ -1071,6 +1111,11 @@ class MessagesDbAsync final : public MessagesDbAsyncInterface {
promise.set_result(sync_db_->get_dialog_message_by_date(dialog_id, first_message_id, last_message_id, date));
}
void get_dialog_message_calendar(MessagesDbDialogCalendarQuery query, Promise<MessagesDbCalendar> promise) {
add_read_query();
promise.set_result(sync_db_->get_dialog_message_calendar(std::move(query)));
}
void get_messages(MessagesDbMessagesQuery query, Promise<vector<MessagesDbDialogMessage>> promise) {
add_read_query();
promise.set_result(sync_db_->get_messages(std::move(query)));

View File

@ -46,6 +46,18 @@ struct MessagesDbMessage {
BufferSlice data;
};
struct MessagesDbDialogCalendarQuery {
DialogId dialog_id;
MessageSearchFilter filter{MessageSearchFilter::Empty};
MessageId from_message_id;
int32 tz_offset{0};
};
struct MessagesDbCalendar {
vector<MessagesDbDialogMessage> messages;
vector<int32> total_counts;
};
struct MessagesDbFtsQuery {
string query;
DialogId dialog_id;
@ -90,6 +102,8 @@ class MessagesDbSyncInterface {
virtual Result<MessagesDbDialogMessage> get_dialog_message_by_date(DialogId dialog_id, MessageId first_message_id,
MessageId last_message_id, int32 date) = 0;
virtual Result<MessagesDbCalendar> get_dialog_message_calendar(MessagesDbDialogCalendarQuery query) = 0;
virtual Result<vector<MessagesDbDialogMessage>> get_messages(MessagesDbMessagesQuery query) = 0;
virtual Result<vector<MessagesDbDialogMessage>> get_scheduled_messages(DialogId dialog_id, int32 limit) = 0;
virtual Result<vector<MessagesDbDialogMessage>> get_messages_from_notification_id(DialogId dialog_id,
@ -141,6 +155,9 @@ class MessagesDbAsyncInterface {
virtual void get_dialog_message_by_date(DialogId dialog_id, MessageId first_message_id, MessageId last_message_id,
int32 date, Promise<MessagesDbDialogMessage> promise) = 0;
virtual void get_dialog_message_calendar(MessagesDbDialogCalendarQuery query,
Promise<MessagesDbCalendar> promise) = 0;
virtual void get_messages(MessagesDbMessagesQuery query, Promise<vector<MessagesDbDialogMessage>> promise) = 0;
virtual void get_scheduled_messages(DialogId dialog_id, int32 limit,
Promise<vector<MessagesDbDialogMessage>> promise) = 0;

View File

@ -67,6 +67,7 @@
#include "td/utils/format.h"
#include "td/utils/misc.h"
#include "td/utils/PathView.h"
#include "td/utils/port/Clocks.h"
#include "td/utils/Random.h"
#include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h"
@ -21529,7 +21530,21 @@ td_api::object_ptr<td_api::messageCalendar> MessagesManager::get_dialog_message_
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
LOG(INFO) << "Get message calendar from database in " << dialog_id << " from " << fixed_from_message_id;
auto new_promise =
PromiseCreator::lambda([random_id, dialog_id, fixed_from_message_id, first_db_message_id, filter,
promise = std::move(promise)](Result<MessagesDbCalendar> r_calendar) mutable {
send_closure(G()->messages_manager(), &MessagesManager::on_get_message_calendar_from_database, random_id,
dialog_id, fixed_from_message_id, first_db_message_id, filter, std::move(r_calendar),
std::move(promise));
});
MessagesDbDialogCalendarQuery db_query;
db_query.dialog_id = dialog_id;
db_query.filter = filter;
db_query.from_message_id = fixed_from_message_id;
db_query.tz_offset = Clocks::tz_offset();
G()->td_db()->get_messages_db_async()->get_dialog_message_calendar(db_query, std::move(new_promise));
return {};
}
}
if (filter == MessageSearchFilter::FailedToSend) {
@ -21557,6 +21572,60 @@ td_api::object_ptr<td_api::messageCalendar> MessagesManager::get_dialog_message_
return {};
}
void MessagesManager::on_get_message_calendar_from_database(int64 random_id, DialogId dialog_id,
MessageId from_message_id, MessageId first_db_message_id,
MessageSearchFilter filter,
Result<MessagesDbCalendar> r_calendar,
Promise<Unit> promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
if (r_calendar.is_error()) {
LOG(ERROR) << "Failed to get message calendar from the database: " << r_calendar.error();
if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat &&
filter != MessageSearchFilter::FailedToSend) {
found_dialog_message_calendars_.erase(random_id);
}
return promise.set_value(Unit());
}
CHECK(!from_message_id.is_scheduled());
CHECK(!first_db_message_id.is_scheduled());
auto calendar = r_calendar.move_as_ok();
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
auto it = found_dialog_message_calendars_.find(random_id);
CHECK(it != found_dialog_message_calendars_.end());
CHECK(it->second == nullptr);
vector<std::pair<MessageId, int32>> periods;
periods.reserve(calendar.messages.size());
for (size_t i = 0; i < calendar.messages.size(); i++) {
auto m = on_get_message_from_database(d, calendar.messages[i], false, "on_get_message_calendar_from_database");
if (m != nullptr && first_db_message_id <= m->message_id) {
CHECK(!m->message_id.is_scheduled());
periods.emplace_back(m->message_id, calendar.total_counts[i]);
}
}
if (periods.empty() && first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat) {
LOG(INFO) << "No messages found in database";
found_dialog_message_calendars_.erase(it);
} else {
auto total_count = d->message_count_by_index[message_search_filter_index(filter)];
vector<td_api::object_ptr<td_api::messageCalendarDay>> days;
for (auto &period : periods) {
const auto *m = get_message(d, period.first);
CHECK(m != nullptr);
days.push_back(td_api::make_object<td_api::messageCalendarDay>(
period.second, get_message_object(dialog_id, m, "on_get_message_calendar_from_database")));
}
it->second = td_api::make_object<td_api::messageCalendar>(total_count, Clocks::tz_offset(), std::move(days));
}
promise.set_value(Unit());
}
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,
@ -22233,7 +22302,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo
MessageId from_message_id, MessageId first_db_message_id,
MessageSearchFilter filter, int32 offset, int32 limit,
Result<vector<MessagesDbDialogMessage>> r_messages,
Promise<> promise) {
Promise<Unit> promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
if (r_messages.is_error()) {
@ -22287,7 +22356,7 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo
}
it->second.first = message_count;
if (res.empty() && first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat) {
LOG(INFO) << "No messages in database found";
LOG(INFO) << "No messages found in database";
found_dialog_messages_.erase(it);
} else {
LOG(INFO) << "Found " << res.size() << " messages out of " << message_count << " in database";
@ -22437,7 +22506,7 @@ void MessagesManager::on_messages_db_calls_result(Result<MessagesDbCallsResult>
it->second.first = calls_db_state_.message_count_by_index[call_message_search_filter_index(filter)];
if (res.empty() && first_db_message_id != MessageId::min()) {
LOG(INFO) << "No messages in database found";
LOG(INFO) << "No messages found in database";
found_call_messages_.erase(it);
}

View File

@ -2817,13 +2817,17 @@ class MessagesManager final : public Actor {
static MessageId get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter);
void on_get_message_calendar_from_database(int64 random_id, DialogId dialog_id, MessageId from_message_id,
MessageId first_db_message_id, MessageSearchFilter filter,
Result<MessagesDbCalendar> r_calendar, Promise<Unit> promise);
void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id,
MessageId first_db_message_id, MessageSearchFilter filter, int32 offset,
int32 limit, Result<vector<MessagesDbDialogMessage>> r_messages,
Promise<> promise);
Promise<Unit> promise);
void on_messages_db_fts_result(Result<MessagesDbFtsResult> result, string offset, int32 limit, int64 random_id,
Promise<> &&promise);
Promise<Unit> &&promise);
void on_messages_db_calls_result(Result<MessagesDbCallsResult> result, int64 random_id, MessageId first_db_message_id,
MessageSearchFilter filter, Promise<Unit> &&promise);