Support MESSAGE_DELETED push notification.

GitOrigin-RevId: f35ce15d7dd2df17486960181d9c54b238abc179
This commit is contained in:
levlam 2019-04-07 18:48:09 +03:00
parent bbde601863
commit 9e2933337f
4 changed files with 160 additions and 56 deletions

View File

@ -10301,9 +10301,8 @@ void MessagesManager::set_dialog_pinned_message_notification(Dialog *d, MessageI
remove_message_notification_id(d, m, true, false);
on_message_changed(d, m, false, "set_dialog_pinned_message_notification");
} else if (d->mention_notification_group.group_id.is_valid()) {
// remove temporary notification
send_closure_later(G()->notification_manager(), &NotificationManager::remove_notification_by_message_id,
} else {
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_message_id,
d->mention_notification_group.group_id, old_message_id);
}
}
@ -10900,6 +10899,7 @@ void MessagesManager::remove_message_notification_id(Dialog *d, Message *m, bool
<< '/' << d->dialog_id << " from database, was_active = " << had_active_notification
<< ", is_permanent = " << is_permanent;
delete_notification_id_to_message_id_correspondence(d, notification_id, m->message_id);
m->removed_notification_id = m->notification_id;
m->notification_id = NotificationId();
if (d->pinned_message_notification_message_id == m->message_id && is_permanent) {
remove_dialog_pinned_message_notification(d); // must be called after notification_id is removed
@ -10980,7 +10980,7 @@ void MessagesManager::do_fix_dialog_last_notification_id(DialogId dialog_id, boo
CHECK(d != nullptr);
auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group;
VLOG(notifications) << "Receive " << result.ok().size() << " message notifications in " << group_info.group_id << '/'
<< dialog_id;
<< dialog_id << " from " << prev_last_notification_id;
if (group_info.last_notification_id != prev_last_notification_id) {
// last_notification_id was changed
return;
@ -18355,7 +18355,7 @@ Result<MessagesManager::MessagePushNotificationInfo> MessagesManager::get_messag
}
if (random_id != 0) {
CHECK(dialog_id.get_type() == DialogType::SecretChat);
if (get_message_id_by_random_id(d, random_id, "need_message_push_notification").is_valid()) {
if (get_message_id_by_random_id(d, random_id, "get_message_push_notification_info").is_valid()) {
return Status::Error(406, "Ignore notification about known secret message");
}
}
@ -18611,12 +18611,38 @@ vector<Notification> MessagesManager::get_message_notifications_from_database_fo
for (auto &message : messages) {
auto m = on_get_message_from_database(d->dialog_id, d, std::move(message),
"get_message_notifications_from_database_force");
if (m == nullptr || !m->notification_id.is_valid() || is_from_mention_notification_group(d, m) != from_mentions) {
// notification_id can be empty if it is deleted in memory, but not in the database
if (m == nullptr) {
VLOG(notifications) << "Receive from database a broken message";
continue;
}
if (m->notification_id.get() <= group_info.max_removed_notification_id.get() ||
auto notification_id = m->notification_id.is_valid() ? m->notification_id : m->removed_notification_id;
if (!notification_id.is_valid()) {
VLOG(ERROR) << "Can't find notification ID for " << m->message_id << " in " << d->dialog_id;
continue;
}
CHECK(m->message_id.is_valid());
bool is_correct = true;
if (notification_id.get() >= from_notification_id.get()) {
// possible if two messages has the same notification_id
LOG(ERROR) << "Have nonmonotoic notification ids: " << d->dialog_id << " " << m->message_id << " "
<< notification_id << " " << from_message_id << " " << from_notification_id;
is_correct = false;
} else {
from_notification_id = notification_id;
is_found = true;
}
if (m->message_id.get() >= from_message_id.get()) {
LOG(ERROR) << "Have nonmonotoic message ids: " << d->dialog_id << " " << m->message_id << " " << notification_id
<< " " << from_message_id << " " << from_notification_id;
is_correct = false;
} else {
from_message_id = m->message_id;
is_found = true;
}
if (notification_id.get() <= group_info.max_removed_notification_id.get() ||
m->message_id.get() <= group_info.max_removed_message_id.get() ||
(!from_mentions && m->message_id.get() <= d->last_read_inbox_message_id.get())) {
// if message still has notification_id, but it was removed via max_removed_notification_id,
@ -18626,37 +18652,33 @@ vector<Notification> MessagesManager::get_message_notifications_from_database_fo
break;
}
if (!m->notification_id.is_valid()) {
// notification_id can be empty if it is deleted in memory, but not in the database
VLOG(notifications) << "Receive from database " << m->message_id << " with removed "
<< m->removed_notification_id;
continue;
}
if (is_from_mention_notification_group(d, m) != from_mentions) {
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
<< " from another group";
continue;
}
if (!is_message_notification_active(d, m)) {
CHECK(from_mentions);
CHECK(!m->contains_unread_mention);
CHECK(m->message_id != d->pinned_message_notification_message_id);
// skip read mentions
continue;
}
bool is_correct = true;
if (m->notification_id.get() >= from_notification_id.get()) {
// possible if two messages has the same notification_id
LOG(ERROR) << "Have nonmonotoic notification ids: " << d->dialog_id << " " << m->message_id << " "
<< m->notification_id << " " << from_message_id << " " << from_notification_id;
is_correct = false;
} else {
from_notification_id = m->notification_id;
is_found = true;
}
if (m->message_id.get() >= from_message_id.get()) {
LOG(ERROR) << "Have nonmonotoic message ids: " << d->dialog_id << " " << m->message_id << " "
<< m->notification_id << " " << from_message_id << " " << from_notification_id;
is_correct = false;
} else {
from_message_id = m->message_id;
is_found = true;
}
if (is_correct && is_from_mention_notification_group(d, m) == from_mentions) {
if (is_correct) {
// skip mention messages returned among unread messages
res.emplace_back(m->notification_id, m->date, create_new_message_notification(m->message_id));
} else if (!is_correct) {
} else {
remove_message_notification_id(d, m, true, false);
on_message_changed(d, m, false, "get_message_notifications_from_database_force");
}
}
if (!res.empty() || !is_found) {
@ -18832,11 +18854,35 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog
for (auto &message : messages) {
auto m =
on_get_message_from_database(dialog_id, d, std::move(message), "on_get_message_notifications_from_database");
if (m == nullptr || !m->notification_id.is_valid() || is_from_mention_notification_group(d, m) != from_mentions) {
if (m == nullptr) {
VLOG(notifications) << "Receive from database a broken message";
continue;
}
if (m->notification_id.get() <= group_info.max_removed_notification_id.get() ||
auto notification_id = m->notification_id.is_valid() ? m->notification_id : m->removed_notification_id;
if (!notification_id.is_valid()) {
VLOG(ERROR) << "Can't find notification ID for " << m->message_id << " in " << d->dialog_id;
continue;
}
CHECK(m->message_id.is_valid());
bool is_correct = true;
if (from_notification_id.is_valid() && notification_id.get() >= from_notification_id.get()) {
LOG(ERROR) << "Receive " << m->message_id << "/" << notification_id << " after " << from_message_id << "/"
<< from_notification_id;
is_correct = false;
} else {
from_notification_id = notification_id;
}
if (from_message_id.is_valid() && m->message_id.get() >= from_message_id.get()) {
LOG(ERROR) << "Receive " << m->message_id << "/" << notification_id << " after " << from_message_id << "/"
<< from_notification_id;
is_correct = false;
} else {
from_message_id = m->message_id;
}
if (notification_id.get() <= group_info.max_removed_notification_id.get() ||
m->message_id.get() <= group_info.max_removed_message_id.get() ||
(!from_mentions && m->message_id.get() <= d->last_read_inbox_message_id.get())) {
// if message still has notification_id, but it was removed via max_removed_notification_id,
@ -18846,34 +18892,33 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog
break;
}
if (!m->notification_id.is_valid()) {
// notification_id can be empty if it is deleted in memory, but not in the database
VLOG(notifications) << "Receive from database " << m->message_id << " with removed "
<< m->removed_notification_id;
continue;
}
if (is_from_mention_notification_group(d, m) != from_mentions) {
VLOG(notifications) << "Receive from database " << m->message_id << " with " << m->notification_id
<< " from another category";
continue;
}
if (!is_message_notification_active(d, m)) {
CHECK(from_mentions);
CHECK(!m->contains_unread_mention);
CHECK(m->message_id != d->pinned_message_notification_message_id);
// skip read mentions
continue;
}
bool is_correct = true;
if (from_notification_id.is_valid() && m->notification_id.get() >= from_notification_id.get()) {
LOG(ERROR) << "Receive " << m->message_id << "/" << m->notification_id << " after " << from_message_id << "/"
<< from_notification_id;
is_correct = false;
} else {
from_notification_id = m->notification_id;
}
if (from_message_id.is_valid() && m->message_id.get() >= from_message_id.get()) {
LOG(ERROR) << "Receive " << m->message_id << "/" << m->notification_id << " after " << from_message_id << "/"
<< from_notification_id;
is_correct = false;
} else {
from_message_id = m->message_id;
}
if (is_correct && is_from_mention_notification_group(d, m) == from_mentions) {
if (is_correct) {
// skip mention messages returned among unread messages
res.emplace_back(m->notification_id, m->date, create_new_message_notification(m->message_id));
} else if (!is_correct) {
} else {
remove_message_notification_id(d, m, true, false);
on_message_changed(d, m, false, "on_get_message_notifications_from_database");
}
}
if (!res.empty() || !from_notification_id.is_valid() || static_cast<size_t>(limit) > messages.size()) {
@ -18935,6 +18980,39 @@ void MessagesManager::remove_message_notification(DialogId dialog_id, Notificati
}
}
void MessagesManager::remove_message_notifications_by_message_ids(DialogId dialog_id,
const vector<MessageId> &message_ids) {
VLOG(notifications) << "Trying to remove notification about " << message_ids << " in " << dialog_id;
Dialog *d = get_dialog_force(dialog_id);
if (d == nullptr) {
return;
}
bool need_update_dialog_pos = false;
vector<int64> deleted_message_ids;
for (auto message_id : message_ids) {
// can't remove just notification_id, because total_count will stay wrong after restart
// auto m = get_message_force(d, message_id, "remove_message_notifications_by_message_ids");
// if (m != nullptr) {
// remove_message_notification_id(d, m, true, false);
// on_message_changed(d, m, false, "remove_message_notifications_by_message_ids");
// }
auto m =
delete_message(d, message_id, true, &need_update_dialog_pos, "remove_message_notifications_by_message_ids");
if (m == nullptr) {
LOG(INFO) << "Can't delete " << message_id << " because it is not found";
continue;
}
deleted_message_ids.push_back(m->message_id.get());
}
if (need_update_dialog_pos) {
send_update_chat_last_message(d, "remove_message_notifications_by_message_ids");
}
send_update_delete_messages(dialog_id, std::move(deleted_message_ids), true, false);
}
void MessagesManager::do_remove_message_notification(DialogId dialog_id, bool from_mentions,
NotificationId notification_id, vector<BufferSlice> result) {
if (result.empty()) {

View File

@ -721,6 +721,8 @@ class MessagesManager : public Actor {
void remove_message_notification(DialogId dialog_id, NotificationGroupId group_id, NotificationId notification_id);
void remove_message_notifications_by_message_ids(DialogId dialog_id, const vector<MessageId> &message_ids);
void remove_message_notifications(DialogId dialog_id, NotificationGroupId group_id,
NotificationId max_notification_id, MessageId max_message_id);
@ -865,6 +867,7 @@ class MessagesManager : public Actor {
bool from_database = false;
NotificationId notification_id;
NotificationId removed_notification_id;
int32 views = 0;

View File

@ -1851,9 +1851,13 @@ void NotificationManager::remove_notification(NotificationGroupId group_id, Noti
promise.set_value(Unit());
}
void NotificationManager::remove_notification_by_message_id(NotificationGroupId group_id, MessageId message_id) {
void NotificationManager::remove_temporary_notification_by_message_id(NotificationGroupId group_id,
MessageId message_id) {
if (!group_id.is_valid()) {
return;
}
VLOG(notifications) << "Remove notification for " << message_id << " in " << group_id;
CHECK(group_id.is_valid());
CHECK(message_id.is_valid());
auto group_it = get_group(group_id);
@ -2989,6 +2993,26 @@ Status NotificationManager::process_push_notification_payload(string payload, Pr
return Status::OK();
}
if (loc_key == "MESSAGE_DELETED") {
if (dialog_id.get_type() == DialogType::SecretChat) {
return Status::Error("Receive MESSAGE_DELETED in a secret chat");
}
TRY_RESULT(server_message_ids_str, get_json_object_string_field(custom, "messages", false));
auto server_message_ids = full_split(server_message_ids_str, ',');
vector<MessageId> message_ids;
for (const auto &server_message_id_str : server_message_ids) {
TRY_RESULT(server_message_id_int, to_integer_safe<int32>(server_message_id_str));
ServerMessageId server_message_id(server_message_id_int);
if (!server_message_id.is_valid()) {
return Status::Error("Receive invalid message_id");
}
message_ids.push_back(MessageId(server_message_id));
}
td_->messages_manager_->remove_message_notifications_by_message_ids(dialog_id, message_ids);
promise.set_value(Unit());
return Status::OK();
}
TRY_RESULT(msg_id, get_json_object_int_field(custom, "msg_id"));
ServerMessageId server_message_id(msg_id);
if (server_message_id != ServerMessageId() && !server_message_id.is_valid()) {
@ -3450,10 +3474,9 @@ void NotificationManager::after_get_difference_impl() {
VLOG(notifications) << "After get difference";
vector<NotificationGroupId> to_remove_temporary_notifications_group_ids;
size_t cur_pos = 0;
for (auto it = groups_.begin(); it != groups_.end() && cur_pos < max_notification_group_count_; ++it, cur_pos++) {
const auto &group_key = it->first;
const auto &group = it->second;
for (auto &group_it : groups_) {
const auto &group_key = group_it.first;
const auto &group = group_it.second;
if (running_get_chat_difference_.count(group_key.group_id.get()) == 0 &&
get_temporary_notification_total_count(group) > 0) {
to_remove_temporary_notifications_group_ids.push_back(group_key.group_id);

View File

@ -73,7 +73,7 @@ class NotificationManager : public Actor {
void remove_notification(NotificationGroupId group_id, NotificationId notification_id, bool is_permanent,
bool force_update, Promise<Unit> &&promise);
void remove_notification_by_message_id(NotificationGroupId group_id, MessageId message_id);
void remove_temporary_notification_by_message_id(NotificationGroupId group_id, MessageId message_id);
void remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
MessageId max_message_id, int32 new_total_count, bool force_update,