Merge commit '60edadab90d7aeb8d7a44764344b8848abf5b8bb'

Conflicts:
	td/telegram/MessagesManager.cpp
This commit is contained in:
Andrea Cavalli 2020-11-07 23:10:26 +01:00
commit 6f28ad36af
7 changed files with 355 additions and 158 deletions

View File

@ -9497,10 +9497,17 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
return promise.set_value(Unit());
}
ChannelFull *channel = add_channel_full(channel_id);
bool have_participant_count = (channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_PARTICIPANT_COUNT) != 0;
auto participant_count = have_participant_count ? channel_full->participants_count_ : 0;
auto administrator_count =
(channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT) != 0 ? channel_full->admins_count_ : 0;
auto administrator_count = 0;
if ((channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_ADMINISTRATOR_COUNT) != 0) {
administrator_count = channel_full->admins_count_;
} else if (c->is_megagroup || c->status.is_administrator()) {
// in megagroups and administrated channels don't drop known number of administrators
administrator_count = channel->administrator_count;
}
auto restricted_count =
(channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_BANNED_COUNT) != 0 ? channel_full->banned_count_ : 0;
auto banned_count =
@ -9525,7 +9532,6 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
can_view_statistics = false;
}
ChannelFull *channel = add_channel_full(channel_id);
channel->repair_request_version = 0;
channel->expires_at = Time::now() + CHANNEL_FULL_EXPIRE_TIME;
if (channel->description != channel_full->about_ || channel->participant_count != participant_count ||
@ -9550,12 +9556,11 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
channel->sticker_set_id = sticker_set_id;
channel->is_changed = true;
if (have_participant_count && c->participant_count != participant_count) {
c->participant_count = participant_count;
c->is_changed = true;
update_channel(c, channel_id);
}
}
if (have_participant_count && c->participant_count != participant_count) {
c->participant_count = participant_count;
c->is_changed = true;
update_channel(c, channel_id);
}
if (!channel->is_can_view_statistics_inited) {
channel->is_can_view_statistics_inited = true;

View File

@ -424,51 +424,8 @@ class GetDiscussionMessageQuery : public Td::ResultHandler {
return on_error(id, result_ptr.move_as_error());
}
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive discussion message for " << message_id_ << " in " << dialog_id_ << ": " << to_string(ptr);
td->contacts_manager_->on_get_users(std::move(ptr->users_), "GetDiscussionMessageQuery");
td->contacts_manager_->on_get_chats(std::move(ptr->chats_), "GetDiscussionMessageQuery");
MessageId max_message_id;
MessageId last_read_inbox_message_id;
MessageId last_read_outbox_message_id;
if ((ptr->flags_ & telegram_api::messages_discussionMessage::MAX_ID_MASK) != 0) {
max_message_id = MessageId(ServerMessageId(ptr->max_id_));
}
if ((ptr->flags_ & telegram_api::messages_discussionMessage::READ_INBOX_MAX_ID_MASK) != 0) {
last_read_inbox_message_id = MessageId(ServerMessageId(ptr->read_inbox_max_id_));
}
if ((ptr->flags_ & telegram_api::messages_discussionMessage::READ_OUTBOX_MAX_ID_MASK) != 0) {
last_read_outbox_message_id = MessageId(ServerMessageId(ptr->read_outbox_max_id_));
}
if (expected_dialog_id_ != dialog_id_) {
td->messages_manager_->on_update_read_message_comments(dialog_id_, message_id_, max_message_id,
last_read_inbox_message_id, last_read_outbox_message_id);
}
vector<FullMessageId> full_message_ids;
MessageId top_message_id;
for (auto &message : ptr->messages_) {
auto full_message_id = td->messages_manager_->on_get_message(std::move(message), false, true, false, false, false,
"GetDiscussionMessageQuery");
if (full_message_id.get_message_id().is_valid()) {
full_message_ids.push_back(full_message_id);
if (full_message_id.get_dialog_id() != expected_dialog_id_) {
return on_error(id, Status::Error(500, "Expected messages in a different chat"));
}
if (full_message_id.get_message_id() == expected_message_id_) {
top_message_id = expected_message_id_;
}
}
}
if (!full_message_ids.empty() && !top_message_id.is_valid()) {
top_message_id = full_message_ids.back().get_message_id();
}
if (top_message_id.is_valid()) {
td->messages_manager_->on_update_read_message_comments(expected_dialog_id_, top_message_id, max_message_id,
last_read_inbox_message_id, last_read_outbox_message_id);
}
promise_.set_value(std::move(full_message_ids));
td->messages_manager_->process_discussion_message(result_ptr.move_as_ok(), dialog_id_, message_id_,
expected_dialog_id_, expected_message_id_, std::move(promise_));
}
void on_error(uint64 id, Status status) override {
@ -549,10 +506,19 @@ class GetChannelMessagesQuery : public Td::ResultHandler {
}
}
td->messages_manager_->on_get_empty_messages(DialogId(channel_id_), std::move(empty_message_ids));
td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, false,
"GetChannelMessagesQuery");
promise_.set_value(Unit());
td->messages_manager_->get_channel_difference_if_needed(
DialogId(channel_id_), std::move(info),
PromiseCreator::lambda(
[td = td, 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();
td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, false,
"GetChannelMessagesQuery");
promise.set_value(Unit());
}
}));
}
void on_error(uint64 id, Status status) override {
@ -1694,9 +1660,19 @@ class GetDialogMessageByDateQuery : public Td::ResultHandler {
}
auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetDialogMessageByDateQuery");
td->messages_manager_->on_get_dialog_message_by_date_success(dialog_id_, date_, random_id_,
std::move(info.messages));
promise_.set_value(Unit());
td->messages_manager_->get_channel_difference_if_needed(
dialog_id_, std::move(info),
PromiseCreator::lambda([td = td, dialog_id = dialog_id_, date = date_, random_id = random_id_,
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();
td->messages_manager_->on_get_dialog_message_by_date_success(dialog_id, date, random_id,
std::move(info.messages));
promise.set_value(Unit());
}
}));
}
void on_error(uint64 id, Status status) override {
@ -1759,11 +1735,21 @@ class GetHistoryQuery : public Td::ResultHandler {
}
auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetHistoryQuery");
// TODO use info.total_count, info.pts
td->messages_manager_->on_get_history(dialog_id_, from_message_id_, offset_, limit_, from_the_end_,
std::move(info.messages));
promise_.set_value(Unit());
td->messages_manager_->get_channel_difference_if_needed(
dialog_id_, std::move(info),
PromiseCreator::lambda([td = td, dialog_id = dialog_id_, from_message_id = from_message_id_, offset = offset_,
limit = limit_, from_the_end = from_the_end_,
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();
// TODO use info.total_count, info.pts
td->messages_manager_->on_get_history(dialog_id, from_message_id, offset, limit, from_the_end,
std::move(info.messages));
promise.set_value(Unit());
}
}));
}
void on_error(uint64 id, Status status) override {
@ -1962,11 +1948,23 @@ class SearchMessagesQuery : public Td::ResultHandler {
}
auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "SearchMessagesQuery");
td->messages_manager_->on_get_dialog_messages_search_result(dialog_id_, query_, sender_dialog_id_, from_message_id_,
offset_, limit_, filter_, top_thread_message_id_,
random_id_, info.total_count, std::move(info.messages));
promise_.set_value(Unit());
td->messages_manager_->get_channel_difference_if_needed(
dialog_id_, std::move(info),
PromiseCreator::lambda([td = td, dialog_id = dialog_id_, query = std::move(query_),
sender_dialog_id = sender_dialog_id_, from_message_id = from_message_id_,
offset = offset_, limit = limit_, filter = filter_,
top_thread_message_id = top_thread_message_id_, random_id = random_id_,
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();
td->messages_manager_->on_get_dialog_messages_search_result(
dialog_id, query, sender_dialog_id, from_message_id, offset, limit, filter, top_thread_message_id,
random_id, info.total_count, std::move(info.messages));
promise.set_value(Unit());
}
}));
}
void on_error(uint64 id, Status status) override {
@ -2113,10 +2111,19 @@ class GetRecentLocationsQuery : public Td::ResultHandler {
}
auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetRecentLocationsQuery");
td->messages_manager_->on_get_recent_locations(dialog_id_, limit_, random_id_, info.total_count,
std::move(info.messages));
promise_.set_value(Unit());
td->messages_manager_->get_channel_difference_if_needed(
dialog_id_, std::move(info),
PromiseCreator::lambda([td = td, dialog_id = dialog_id_, limit = limit_, random_id = random_id_,
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();
td->messages_manager_->on_get_recent_locations(dialog_id, limit, random_id, info.total_count,
std::move(info.messages));
promise.set_value(Unit());
}
}));
}
void on_error(uint64 id, Status status) override {
@ -9028,6 +9035,23 @@ MessagesManager::MessagesInfo MessagesManager::on_get_messages(
return result;
}
void MessagesManager::get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info,
Promise<MessagesInfo> &&promise) {
for (auto &message : messages_info.messages) {
if (need_channel_difference_to_add_message(dialog_id, message)) {
return run_after_channel_difference(dialog_id,
PromiseCreator::lambda([messages_info = std::move(messages_info),
promise = std::move(promise)](Unit ignored) mutable {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
promise.set_value(std::move(messages_info));
}));
}
}
promise.set_value(std::move(messages_info));
}
void MessagesManager::on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message,
bool is_scheduled, const char *source) {
LOG(DEBUG) << "Receive " << messages.size() << " messages";
@ -16315,27 +16339,10 @@ void MessagesManager::get_message_force_from_server(Dialog *d, MessageId message
auto m = get_message_force(d, message_id, "get_message_force_from_server");
if (m == nullptr) {
if (message_id.is_valid() && message_id.is_server()) {
if (d->last_new_message_id != MessageId() && message_id > d->last_new_message_id) {
if (d->last_new_message_id != MessageId() && message_id > d->last_new_message_id &&
dialog_type != DialogType::Channel) {
// message will not be added to the dialog anyway
if (dialog_type == DialogType::Channel) {
// so we try to force channel difference first
// replied message can't be older than already added original message
LOG_CHECK(input_message == nullptr || input_message->get_id() != telegram_api::inputMessageReplyTo::ID)
<< to_string(input_message) << " " << d->dialog_id << " " << message_id << " " << d->last_new_message_id
<< " " << d->last_message_id << " " << d->first_database_message_id << " " << d->last_database_message_id
<< " " << d->last_pinned_message_id << " " << d->last_read_all_mentions_message_id << " "
<< d->max_unavailable_message_id << " " << d->last_clear_history_message_id << " " << d->order << " "
<< d->deleted_last_message_id << " " << d->max_added_message_id << " " << d->pts << " "
<< d->last_assigned_message_id << " " << d->debug_last_new_message_id << " "
<< d->debug_first_database_message_id << " " << d->debug_last_database_message_id;
postponed_get_message_requests_[d->dialog_id].emplace_back(message_id, std::move(promise),
std::move(input_message));
get_channel_difference(d->dialog_id, d->pts, true, "get_message");
} else {
promise.set_value(Unit());
}
return;
return promise.set_value(Unit());
}
if (d->deleted_message_ids.count(message_id) == 0 && dialog_type != DialogType::SecretChat) {
@ -16475,6 +16482,84 @@ void MessagesManager::get_message_thread(DialogId dialog_id, MessageId message_i
top_thread_full_message_id.get_message_id());
}
void MessagesManager::process_discussion_message(
telegram_api::object_ptr<telegram_api::messages_discussionMessage> &&result, DialogId dialog_id,
MessageId message_id, DialogId expected_dialog_id, MessageId expected_message_id,
Promise<vector<FullMessageId>> promise) {
LOG(INFO) << "Receive discussion message for " << message_id << " in " << dialog_id << ": " << to_string(result);
td_->contacts_manager_->on_get_users(std::move(result->users_), "process_discussion_message");
td_->contacts_manager_->on_get_chats(std::move(result->chats_), "process_discussion_message");
for (auto &message : result->messages_) {
auto message_dialog_id = get_message_dialog_id(message);
if (message_dialog_id != expected_dialog_id) {
return promise.set_error(Status::Error(500, "Expected messages in a different chat"));
}
}
for (auto &message : result->messages_) {
if (need_channel_difference_to_add_message(expected_dialog_id, message)) {
return run_after_channel_difference(
expected_dialog_id, PromiseCreator::lambda([actor_id = actor_id(this), result = std::move(result), dialog_id,
message_id, expected_dialog_id, expected_message_id,
promise = std::move(promise)](Unit ignored) mutable {
send_closure(actor_id, &MessagesManager::process_discussion_message_impl, std::move(result), dialog_id,
message_id, expected_dialog_id, expected_message_id, std::move(promise));
}));
}
}
process_discussion_message_impl(std::move(result), dialog_id, message_id, expected_dialog_id, expected_message_id,
std::move(promise));
}
void MessagesManager::process_discussion_message_impl(
telegram_api::object_ptr<telegram_api::messages_discussionMessage> &&result, DialogId dialog_id,
MessageId message_id, DialogId expected_dialog_id, MessageId expected_message_id,
Promise<vector<FullMessageId>> promise) {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
MessageId max_message_id;
MessageId last_read_inbox_message_id;
MessageId last_read_outbox_message_id;
if ((result->flags_ & telegram_api::messages_discussionMessage::MAX_ID_MASK) != 0) {
max_message_id = MessageId(ServerMessageId(result->max_id_));
}
if ((result->flags_ & telegram_api::messages_discussionMessage::READ_INBOX_MAX_ID_MASK) != 0) {
last_read_inbox_message_id = MessageId(ServerMessageId(result->read_inbox_max_id_));
}
if ((result->flags_ & telegram_api::messages_discussionMessage::READ_OUTBOX_MAX_ID_MASK) != 0) {
last_read_outbox_message_id = MessageId(ServerMessageId(result->read_outbox_max_id_));
}
vector<FullMessageId> full_message_ids;
MessageId top_message_id;
for (auto &message : result->messages_) {
auto full_message_id =
on_get_message(std::move(message), false, true, false, false, false, "process_discussion_message");
if (full_message_id.get_message_id().is_valid()) {
full_message_ids.push_back(full_message_id);
if (full_message_id.get_message_id() == expected_message_id) {
top_message_id = expected_message_id;
}
}
}
if (!full_message_ids.empty() && !top_message_id.is_valid()) {
top_message_id = full_message_ids.back().get_message_id();
}
if (top_message_id.is_valid()) {
on_update_read_message_comments(expected_dialog_id, top_message_id, max_message_id, last_read_inbox_message_id,
last_read_outbox_message_id);
}
if (expected_dialog_id != dialog_id) {
on_update_read_message_comments(dialog_id, message_id, max_message_id, last_read_inbox_message_id,
last_read_outbox_message_id);
}
promise.set_value(std::move(full_message_ids));
}
void MessagesManager::on_get_discussion_message(DialogId dialog_id, MessageId message_id,
vector<FullMessageId> full_message_ids,
Promise<MessageThreadInfo> &&promise) {
@ -24389,6 +24474,23 @@ int32 MessagesManager::get_message_schedule_date(const Message *m) {
return m->date;
}
DialogId MessagesManager::get_message_original_sender(const Message *m) {
if (m->forward_info != nullptr) {
auto forward_info = m->forward_info.get();
if (is_forward_info_sender_hidden(forward_info)) {
return DialogId();
}
if (forward_info->message_id.is_valid() || forward_info->sender_dialog_id.is_valid()) {
return forward_info->sender_dialog_id;
}
return DialogId(forward_info->sender_user_id);
}
if (m->sender_dialog_id.is_valid()) {
return m->sender_dialog_id;
}
return DialogId(m->sender_user_id);
}
void MessagesManager::edit_message_text(FullMessageId full_message_id,
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
@ -25622,6 +25724,13 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
};
vector<CopiedMessage> copied_messages;
struct ForwardedMessageContent {
unique_ptr<MessageContent> content;
int64 media_album_id;
size_t index;
};
vector<ForwardedMessageContent> forwarded_message_contents;
std::unordered_map<int64, std::pair<int64, int32>> new_media_album_ids;
auto my_id = td_->contacts_manager_->get_my_id();
@ -25629,7 +25738,7 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
for (size_t i = 0; i < message_ids.size(); i++) {
MessageId message_id = get_persistent_message_id(from_dialog, message_ids[i]);
Message *forwarded_message = get_message_force(from_dialog, message_id, "forward_messages");
const Message *forwarded_message = get_message_force(from_dialog, message_id, "forward_messages");
if (forwarded_message == nullptr) {
LOG(INFO) << "Can't find " << message_id << " to forward";
continue;
@ -25688,9 +25797,35 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
copied_messages.push_back({std::move(content), top_thread_message_id, reply_to_message_id,
std::move(reply_markup), forwarded_message->media_album_id,
get_message_disable_web_page_preview(forwarded_message), i});
continue;
} else {
forwarded_message_contents.push_back({std::move(content), forwarded_message->media_album_id, i});
}
}
if (2 <= forwarded_message_contents.size() && forwarded_message_contents.size() <= MAX_GROUPED_MESSAGES) {
std::unordered_set<MessageContentType, MessageContentTypeHash> message_content_types;
std::unordered_set<DialogId, DialogIdHash> sender_dialog_ids;
for (auto &message_content : forwarded_message_contents) {
message_content_types.insert(message_content.content->get_type());
MessageId message_id = get_persistent_message_id(from_dialog, message_ids[message_content.index]);
sender_dialog_ids.insert(get_message_original_sender(get_message(from_dialog, message_id)));
}
if (message_content_types.size() == 1 && is_homogenous_media_group_content(*message_content_types.begin()) &&
sender_dialog_ids.size() == 1 && *sender_dialog_ids.begin() != DialogId()) {
new_media_album_ids[0].first = generate_new_media_album_id();
for (auto &message : forwarded_message_contents) {
message.media_album_id = 0;
}
}
}
for (size_t j = 0; j < forwarded_message_contents.size(); j++) {
MessageId message_id = get_persistent_message_id(from_dialog, message_ids[forwarded_message_contents[j].index]);
const Message *forwarded_message = get_message(from_dialog, message_id);
CHECK(forwarded_message != nullptr);
auto content = std::move(forwarded_message_contents[j].content);
auto content_type = content->get_type();
bool is_game = content_type == MessageContentType::Game;
unique_ptr<MessageForwardInfo> forward_info;
@ -25731,17 +25866,13 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
}
Message *m = get_message_to_send(to_dialog, MessageId(), MessageId(), message_send_options, std::move(content),
&need_update_dialog_pos, i + 1 != message_ids.size(), std::move(forward_info));
&need_update_dialog_pos, j + 1 != forwarded_message_contents.size(),
std::move(forward_info));
m->real_forward_from_dialog_id = from_dialog_id;
m->real_forward_from_message_id = message_id;
m->via_bot_user_id = forwarded_message->via_bot_user_id;
m->in_game_share = in_game_share;
m->media_album_id = forwarded_message->media_album_id;
if (forwarded_message->view_count > 0 && is_broadcast_channel(from_dialog_id)) {
forwarded_message->forward_count++;
send_update_message_interaction_info(from_dialog_id, forwarded_message);
on_message_changed(from_dialog, forwarded_message, true, "forward_messages");
}
m->media_album_id = new_media_album_ids[forwarded_message_contents[j].media_album_id].first;
if (forwarded_message->view_count > 0 && m->forward_info != nullptr && m->view_count == 0 &&
!(m->message_id.is_scheduled() && is_broadcast_channel(to_dialog_id))) {
m->view_count = forwarded_message->view_count;
@ -25789,32 +25920,38 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
}
}
result[i] = m->message_id;
send_update_new_message(to_dialog, m);
result[forwarded_message_contents[j].index] = m->message_id;
forwarded_messages.push_back(m);
forwarded_message_ids.push_back(message_id);
}
if (!forwarded_messages.empty()) {
for (auto m : forwarded_messages) {
if (m->media_album_id != 0) {
m->media_album_id = new_media_album_ids[m->media_album_id].first;
}
send_update_new_message(to_dialog, m);
}
do_forward_messages(to_dialog_id, from_dialog_id, forwarded_messages, forwarded_message_ids, 0);
}
new_media_album_ids.erase(0);
if (2 <= copied_messages.size() && copied_messages.size() <= MAX_GROUPED_MESSAGES) {
std::unordered_set<MessageContentType, MessageContentTypeHash> message_content_types;
for (auto &copied_message : copied_messages) {
message_content_types.insert(copied_message.content->get_type());
}
if (message_content_types.size() == 1 && is_homogenous_media_group_content(*message_content_types.begin())) {
new_media_album_ids[0].first = generate_new_media_album_id();
for (auto &message : copied_messages) {
message.media_album_id = 0;
}
}
}
if (!copied_messages.empty()) {
for (auto &copied_message : copied_messages) {
Message *m = get_message_to_send(
to_dialog, copied_message.top_thread_message_id, copied_message.reply_to_message_id, message_send_options,
std::move(copied_message.content), &need_update_dialog_pos, false, nullptr, true);
m->disable_web_page_preview = copied_message.disable_web_page_preview;
if (copied_message.media_album_id != 0) {
m->media_album_id = new_media_album_ids[copied_message.media_album_id].first;
}
m->media_album_id = new_media_album_ids[copied_message.media_album_id].first;
m->reply_markup = std::move(copied_message.reply_markup);
save_send_message_log_event(to_dialog_id, m);
@ -28884,7 +29021,12 @@ void MessagesManager::drop_dialog_last_pinned_message_id(Dialog *d) {
LOG(INFO) << "Drop " << d->dialog_id << " pinned message";
reload_dialog_info_full(d->dialog_id);
create_actor<SleepActor>(
"ReloadDialogFullInfoActor", 1.0,
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id = d->dialog_id](Result<Unit> result) {
send_closure(actor_id, &MessagesManager::reload_dialog_info_full, dialog_id);
}))
.release();
}
void MessagesManager::repair_dialog_scheduled_messages(Dialog *d) {
@ -31327,12 +31469,12 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
}
if (max_message_id != MessageId() && message_id > max_message_id) {
if (!message->from_database) {
if (!message->is_pinned) {
LOG(DEBUG) << "Ignore " << message_id << " in " << dialog_id << " received not through update from " << source
<< ". Last is " << max_message_id << ", channel difference " << debug_channel_difference_dialog_
<< " " << to_string(get_message_object(dialog_id, message.get()));
}
LOG(DEBUG) << "Ignore " << message_id << " in " << dialog_id << " received not through update from " << source
<< ". Last is " << max_message_id << ", channel difference " << debug_channel_difference_dialog_
<< " " << to_string(get_message_object(dialog_id, message.get()));
dump_debug_message_op(d, 3);
// keep consistent with need_channel_difference_to_add_message
if (dialog_id.get_type() == DialogType::Channel && have_input_peer(dialog_id, AccessRights::Read) &&
dialog_id != debug_channel_difference_dialog_) {
LOG(INFO) << "Schedule getDifference in " << dialog_id.get_channel_id();
@ -34562,6 +34704,36 @@ void MessagesManager::set_channel_pts(Dialog *d, int32 new_pts, const char *sour
}
}
bool MessagesManager::need_channel_difference_to_add_message(DialogId dialog_id,
const tl_object_ptr<telegram_api::Message> &message_ptr) {
if (dialog_id.get_type() != DialogType::Channel || !have_input_peer(dialog_id, AccessRights::Read) ||
dialog_id == debug_channel_difference_dialog_) {
return false;
}
if (get_message_dialog_id(message_ptr) != dialog_id) {
return false;
}
Dialog *d = get_dialog_force(dialog_id);
if (d == nullptr || d->last_new_message_id == MessageId()) {
return false;
}
return get_message_id(message_ptr, false) > d->last_new_message_id;
}
void MessagesManager::run_after_channel_difference(DialogId dialog_id, Promise<Unit> &&promise) {
CHECK(dialog_id.get_type() == DialogType::Channel);
CHECK(have_input_peer(dialog_id, AccessRights::Read));
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
run_after_get_channel_difference_[dialog_id].push_back(std::move(promise));
get_channel_difference(dialog_id, d->pts, true, "run_after_channel_difference");
}
bool MessagesManager::running_get_channel_difference(DialogId dialog_id) const {
return active_get_channel_differencies_.count(dialog_id) > 0;
}
@ -34613,6 +34785,11 @@ void MessagesManager::get_channel_difference(DialogId dialog_id, int32 pts, bool
}
LOG_CHECK(dialog_id.get_type() == DialogType::Channel) << dialog_id << " " << source;
if (active_get_channel_differencies_.count(dialog_id)) {
LOG(INFO) << "Skip running channels.getDifference for " << dialog_id << " from " << source
<< " because it has already been run";
return;
}
auto input_channel = td_->contacts_manager_->get_input_channel(dialog_id.get_channel_id());
if (input_channel == nullptr) {
LOG(ERROR) << "Skip running channels.getDifference for " << dialog_id << " from " << source
@ -34650,6 +34827,7 @@ void MessagesManager::do_get_channel_difference(DialogId dialog_id, int32 pts, b
<< " because it has already been run";
return;
}
// must work even we know nothing about the dialog
// can be called multiple times before after_get_channel_difference
const Dialog *d = get_dialog(dialog_id);
@ -34853,6 +35031,9 @@ void MessagesManager::on_get_channel_difference(
return;
}
LOG(INFO) << "Receive result of getChannelDifference for " << dialog_id << " with pts = " << request_pts
<< " and limit = " << request_limit << ": " << to_string(difference_ptr);
switch (difference_ptr->get_id()) {
case telegram_api::updates_channelDifferenceEmpty::ID:
if (d == nullptr) {
@ -34887,9 +35068,6 @@ void MessagesManager::on_get_channel_difference(
LOG_IF(ERROR, cur_pts != request_pts) << "Channel pts has changed from " << request_pts << " to " << d->pts << " in "
<< dialog_id << " during getChannelDifference";
LOG(INFO) << "Receive result of getChannelDifference for " << dialog_id << " with pts = " << request_pts
<< " and limit = " << request_limit << ": " << to_string(difference_ptr);
d->retry_get_difference_timeout = 1;
bool is_final = true;
@ -35087,24 +35265,13 @@ void MessagesManager::after_get_channel_difference(DialogId dialog_id, bool succ
send_update_chat_read_inbox(d, true, "after_get_channel_difference");
}
auto it_get_message_requests = postponed_get_message_requests_.find(dialog_id);
if (it_get_message_requests != postponed_get_message_requests_.end()) {
if (d == nullptr) {
LOG(ERROR) << "Unknown dialog " << dialog_id;
return;
}
auto requests = std::move(it_get_message_requests->second);
postponed_get_message_requests_.erase(it_get_message_requests);
for (auto &request : requests) {
auto message_id = request.message_id;
LOG(INFO) << "Run postponed getMessage request for " << message_id << " in " << dialog_id;
CHECK(message_id.is_valid());
if (d->last_new_message_id != MessageId() && message_id > d->last_new_message_id) {
// message will not be added to the dialog anyway, get channel difference didn't help
request.promise.set_value(Unit());
} else {
get_message_from_server({dialog_id, message_id}, std::move(request.promise), std::move(request.input_message));
}
auto promise_it = run_after_get_channel_difference_.find(dialog_id);
if (promise_it != run_after_get_channel_difference_.end()) {
vector<Promise<Unit>> promises = std::move(promise_it->second);
run_after_get_channel_difference_.erase(promise_it);
for (auto &promise : promises) {
promise.set_value(Unit());
}
}

View File

@ -238,6 +238,9 @@ class MessagesManager : public Actor {
};
MessagesInfo on_get_messages(tl_object_ptr<telegram_api::messages_Messages> &&messages_ptr, const char *source);
void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info,
Promise<MessagesInfo> &&promise);
void on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message,
bool is_scheduled, const char *source);
@ -612,8 +615,9 @@ class MessagesManager : public Actor {
td_api::object_ptr<td_api::messageThreadInfo> get_message_thread_info_object(const MessageThreadInfo &info);
void on_get_discussion_message(DialogId dialog_id, MessageId message_id, vector<FullMessageId> full_message_ids,
Promise<MessageThreadInfo> &&promise);
void process_discussion_message(telegram_api::object_ptr<telegram_api::messages_discussionMessage> &&result,
DialogId dialog_id, MessageId message_id, DialogId expected_dialog_id,
MessageId expected_message_id, Promise<vector<FullMessageId>> promise);
bool is_message_edited_recently(FullMessageId full_message_id, int32 seconds);
@ -809,7 +813,7 @@ class MessagesManager : public Actor {
void on_resolved_username(const string &username, DialogId dialog_id);
void drop_username(const string &username);
tl_object_ptr<telegram_api::InputNotifyPeer> get_input_notify_peer(DialogId dialogId) const;
tl_object_ptr<telegram_api::InputNotifyPeer> get_input_notify_peer(DialogId dialog_id) const;
void on_update_dialog_notify_settings(DialogId dialog_id,
tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings,
@ -2073,7 +2077,7 @@ class MessagesManager : public Actor {
void load_folder_dialog_list_from_database(FolderId folder_id, int32 limit, Promise<Unit> &&promise);
void preload_folder_dialog_list(FolderId folderId);
void preload_folder_dialog_list(FolderId folder_id);
static void invalidate_message_indexes(Dialog *d);
@ -2645,6 +2649,13 @@ class MessagesManager : public Actor {
void on_get_message_link_discussion_message(MessageLinkInfo &&info, DialogId comment_dialog_id,
Promise<MessageLinkInfo> &&promise);
void process_discussion_message_impl(telegram_api::object_ptr<telegram_api::messages_discussionMessage> &&result,
DialogId dialog_id, MessageId message_id, DialogId expected_dialog_id,
MessageId expected_message_id, Promise<vector<FullMessageId>> promise);
void on_get_discussion_message(DialogId dialog_id, MessageId message_id, vector<FullMessageId> full_message_ids,
Promise<MessageThreadInfo> &&promise);
static MessageId get_first_database_message_id_by_index(const Dialog *d, MessageSearchFilter filter);
void on_search_dialog_messages_db_result(int64 random_id, DialogId dialog_id, MessageId from_message_id,
@ -2773,6 +2784,11 @@ class MessagesManager : public Actor {
void set_channel_pts(Dialog *d, int32 new_pts, const char *source);
bool need_channel_difference_to_add_message(DialogId dialog_id,
const tl_object_ptr<telegram_api::Message> &message_ptr);
void run_after_channel_difference(DialogId dialog_id, Promise<Unit> &&promise);
bool running_get_channel_difference(DialogId dialog_id) const;
void on_channel_get_difference_timeout(DialogId dialog_id);
@ -2957,6 +2973,8 @@ class MessagesManager : public Actor {
static int32 get_message_schedule_date(const Message *m);
static DialogId get_message_original_sender(const Message *m);
int32 recently_found_dialogs_loaded_ = 0; // 0 - not loaded, 1 - load request was sent, 2 - loaded
MultiPromiseActor resolve_recently_found_dialogs_multipromise_{"ResolveRecentlyFoundDialogsMultiPromiseActor"};
@ -3090,8 +3108,6 @@ class MessagesManager : public Actor {
}
};
std::unordered_map<DialogId, vector<PendingGetMessageRequest>, DialogIdHash> postponed_get_message_requests_;
std::unordered_map<string, vector<Promise<Unit>>> search_public_dialogs_queries_;
std::unordered_map<string, vector<DialogId>> found_public_dialogs_; // TODO time bound cache
std::unordered_map<string, vector<DialogId>> found_on_server_dialogs_; // TODO time bound cache
@ -3224,6 +3240,8 @@ class MessagesManager : public Actor {
vector<PendingOnGetDialogs> pending_on_get_dialogs_;
std::unordered_map<DialogId, PendingOnGetDialogs, DialogIdHash> pending_channel_on_get_dialogs_;
std::unordered_map<DialogId, vector<Promise<Unit>>, DialogIdHash> run_after_get_channel_difference_;
ChangesProcessor<unique_ptr<PendingSecretMessage>> pending_secret_messages_;
std::unordered_map<DialogId, vector<DialogId>, DialogIdHash>

View File

@ -8,6 +8,7 @@
#include "td/utils/common.h"
#include "td/utils/port/thread.h"
#include "td/utils/type_traits.h"
#include <atomic>
#include <cstring>
@ -21,7 +22,7 @@ class AtomicRead {
public:
void read(T &dest) const {
while (true) {
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
static_assert(TD_IS_TRIVIALLY_COPYABLE(T), "T must be trivially copyable");
auto version_before = version.load();
if (version_before % 2 == 0) {
std::memcpy(&dest, &value, sizeof(dest));

View File

@ -38,7 +38,7 @@ class ThreadLocalStorage {
private:
struct Node {
T value{};
T value;
char padding[TD_CONCURRENCY_PAD];
};
static constexpr int32 MAX_THREAD_ID = 128;

View File

@ -6,6 +6,8 @@
//
#pragma once
#include "td/utils/type_traits.h"
#include <cstring>
#include <type_traits>
@ -64,13 +66,6 @@ class ConstAs {
} // namespace detail
// no std::is_trivially_copyable in libstdc++ before 5.0
#if __GLIBCXX__
#define TD_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
#else
#define TD_IS_TRIVIALLY_COPYABLE(T) ::std::is_trivially_copyable<T>::value
#endif
template <class ToT, class FromT,
std::enable_if_t<TD_IS_TRIVIALLY_COPYABLE(ToT) && TD_IS_TRIVIALLY_COPYABLE(FromT), int> = 0>
detail::As<ToT> as(FromT *from) {

View File

@ -6,6 +6,10 @@
//
#pragma once
#include "td/utils/int_types.h"
#include <type_traits>
namespace td {
template <class FunctionT>
@ -27,4 +31,11 @@ constexpr size_t member_function_argument_count() {
return member_function_class<FunctionT>::argument_count();
}
// no std::is_trivially_copyable in libstdc++ before 5.0
#if __GLIBCXX__
#define TD_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
#else
#define TD_IS_TRIVIALLY_COPYABLE(T) ::std::is_trivially_copyable<T>::value
#endif
} // namespace td