Add class NotificationObjectId.

This commit is contained in:
levlam 2023-08-25 02:04:44 +03:00
parent c770f6058c
commit 4455255d9b
8 changed files with 162 additions and 81 deletions

View File

@ -723,6 +723,7 @@ set(TDLIB_SOURCE
td/telegram/NotificationGroupType.h
td/telegram/NotificationId.h
td/telegram/NotificationManager.h
td/telegram/NotificationObjectId.h
td/telegram/NotificationSettingsScope.h
td/telegram/NotificationSettingsManager.h
td/telegram/NotificationSound.h

View File

@ -52,6 +52,7 @@
#include "td/telegram/NotificationGroupInfo.hpp"
#include "td/telegram/NotificationGroupType.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationObjectId.h"
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/NotificationSound.h"
#include "td/telegram/NotificationType.h"
@ -15320,7 +15321,7 @@ void MessagesManager::set_dialog_pinned_message_notification(Dialog *d, MessageI
remove_message_notification_id(d, m, true, false, true);
on_message_changed(d, m, false, source);
} else {
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_message_id,
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_object_id,
notification_info->mention_notification_group_.get_group_id(), old_message_id, false, source);
}
}
@ -29285,11 +29286,12 @@ void MessagesManager::try_add_pinned_message_notification(Dialog *d, vector<Noti
auto pos = res.size();
res.emplace_back(m->notification_id, m->date, m->disable_notification,
create_new_message_notification(message_id, is_message_preview_enabled(d, m, true)));
while (pos > 0 && res[pos - 1].type->get_message_id() < message_id) {
NotificationObjectId object_id(message_id);
while (pos > 0 && res[pos - 1].type->get_object_id() < object_id) {
std::swap(res[pos - 1], res[pos]);
pos--;
}
if (pos > 0 && res[pos - 1].type->get_message_id() == message_id) {
if (pos > 0 && res[pos - 1].type->get_object_id() == object_id) {
res.erase(res.begin() + pos); // notification was already there
}
if (res.size() > static_cast<size_t>(limit)) {
@ -29732,10 +29734,10 @@ void MessagesManager::remove_message_notifications_by_message_ids(DialogId dialo
if (message == nullptr) {
LOG(INFO) << "Can't delete " << message_id << " because it is not found";
// call synchronously to remove them before ProcessPush returns
td_->notification_manager_->remove_temporary_notification_by_message_id(
td_->notification_manager_->remove_temporary_notification_by_object_id(
d->notification_info->message_notification_group_.get_group_id(), message_id, true,
"remove_message_notifications_by_message_ids");
td_->notification_manager_->remove_temporary_notification_by_message_id(
td_->notification_manager_->remove_temporary_notification_by_object_id(
d->notification_info->mention_notification_group_.get_group_id(), message_id, true,
"remove_message_notifications_by_message_ids");
continue;
@ -35561,10 +35563,10 @@ void MessagesManager::delete_message_from_database(Dialog *d, MessageId message_
}
}
} else if (!message_id.is_scheduled() && message_id > d->last_new_message_id && d->notification_info != nullptr) {
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_message_id,
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_object_id,
d->notification_info->message_notification_group_.get_group_id(), message_id, false,
"delete_message_from_database");
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_message_id,
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_object_id,
d->notification_info->mention_notification_group_.get_group_id(), message_id, false,
"delete_message_from_database");
}
@ -36733,7 +36735,7 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
d->notification_info->mention_notification_group_.is_removed_object_id(pinned_message_id.get())) {
VLOG(notifications) << "Remove disabled pinned message notification in " << pinned_message_id << " in "
<< dialog_id;
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_message_id,
send_closure_later(G()->notification_manager(), &NotificationManager::remove_temporary_notification_by_object_id,
d->notification_info->mention_notification_group_.get_group_id(), pinned_message_id, true,
"fix pinned message notification");
d->notification_info->pinned_message_notification_message_id_ = MessageId();

View File

@ -512,49 +512,49 @@ NotificationId NotificationManager::get_last_notification_id(const NotificationG
return NotificationId();
}
MessageId NotificationManager::get_first_message_id(const NotificationGroup &group) {
// it's fine to return MessageId() if first notification has no message_id, because
// non-message notification can't be mixed with message notifications
NotificationObjectId NotificationManager::get_first_object_id(const NotificationGroup &group) {
// it's fine to return NotificationObjectId() if first notification has no object_id, because
// object_id is from the same scope within a notification group
if (!group.notifications.empty()) {
return group.notifications[0].type->get_message_id();
return group.notifications[0].type->get_object_id();
}
if (!group.pending_notifications.empty()) {
return group.pending_notifications[0].type->get_message_id();
return group.pending_notifications[0].type->get_object_id();
}
return MessageId();
return NotificationObjectId();
}
MessageId NotificationManager::get_last_message_id(const NotificationGroup &group) {
// it's fine to return MessageId() if last notification has no message_id, because
// non-message notification can't be mixed with message notifications
NotificationObjectId NotificationManager::get_last_object_id(const NotificationGroup &group) {
// it's fine to return NotificationObjectId() if last notification has no object_id, because
// object_id is from the same scope within a notification group
if (!group.pending_notifications.empty()) {
return group.pending_notifications.back().type->get_message_id();
return group.pending_notifications.back().type->get_object_id();
}
if (!group.notifications.empty()) {
return group.notifications.back().type->get_message_id();
return group.notifications.back().type->get_object_id();
}
return MessageId();
return NotificationObjectId();
}
MessageId NotificationManager::get_last_message_id_by_notification_id(const NotificationGroup &group,
NotificationId max_notification_id) {
NotificationObjectId NotificationManager::get_last_object_id_by_notification_id(const NotificationGroup &group,
NotificationId max_notification_id) {
for (auto &notification : reversed(group.pending_notifications)) {
if (notification.notification_id.get() <= max_notification_id.get()) {
auto message_id = notification.type->get_message_id();
if (message_id.is_valid()) {
return message_id;
auto object_id = notification.type->get_object_id();
if (object_id.is_valid()) {
return object_id;
}
}
}
for (auto &notification : reversed(group.notifications)) {
if (notification.notification_id.get() <= max_notification_id.get()) {
auto message_id = notification.type->get_message_id();
if (message_id.is_valid()) {
return message_id;
auto object_id = notification.type->get_object_id();
if (object_id.is_valid()) {
return object_id;
}
}
}
return MessageId();
return NotificationObjectId();
}
void NotificationManager::load_message_notifications_from_database(const NotificationGroupKey &group_key,
@ -573,13 +573,13 @@ void NotificationManager::load_message_notifications_from_database(const Notific
size_t limit = desired_size - group.notifications.size();
auto first_notification_id = get_first_notification_id(group);
auto from_notification_id = first_notification_id.is_valid() ? first_notification_id : NotificationId::max();
auto first_object_id = get_first_object_id(group);
switch (group.type) {
case NotificationGroupType::SecretChat:
case NotificationGroupType::Messages:
case NotificationGroupType::Mentions: {
auto first_message_id = get_first_message_id(group);
auto from_message_id = first_message_id.is_valid() ? first_message_id : MessageId::max();
auto from_message_id = first_object_id.is_valid() ? MessageId(first_object_id.get()) : MessageId::max();
send_closure(G()->messages_manager(), &MessagesManager::get_message_notifications_from_database,
group_key.dialog_id, group_key.group_id, from_notification_id, from_message_id,
static_cast<int32>(limit),
@ -623,9 +623,9 @@ void NotificationManager::on_get_message_notifications_from_database(Notificatio
notifications.pop_back();
}
}
auto first_message_id = get_first_message_id(group);
if (first_message_id.is_valid()) {
while (!notifications.empty() && notifications.back().type->get_message_id() >= first_message_id) {
auto first_object_id = get_first_object_id(group);
if (first_object_id.is_valid()) {
while (!notifications.empty() && notifications.back().type->get_object_id() >= first_object_id) {
// possible if notifications was added after the database request was sent
notifications.pop_back();
}
@ -912,11 +912,11 @@ void NotificationManager::add_notification(NotificationGroupId group_id, Notific
on_notification_removed(notification_id);
return;
}
auto message_id = type->get_message_id();
if (message_id.is_valid() && message_id <= get_last_message_id(group)) {
auto object_id = type->get_object_id();
if (object_id.is_valid() && object_id <= get_last_object_id(group)) {
LOG(ERROR) << "Failed to add " << notification_id << " of type " << *type << " to " << group_id << " of type "
<< group_type << " in " << dialog_id << ", because have already added notification about "
<< get_last_message_id(group);
<< get_last_object_id(group);
on_notification_removed(notification_id);
return;
}
@ -1665,7 +1665,7 @@ void NotificationManager::edit_notification(NotificationGroupId group_id, Notifi
for (size_t i = 0; i < group.notifications.size(); i++) {
auto &notification = group.notifications[i];
if (notification.notification_id == notification_id) {
if (notification.type->get_message_id() != type->get_message_id() ||
if (notification.type->get_object_id() != type->get_object_id() ||
notification.type->is_temporary() != type->is_temporary()) {
LOG(ERROR) << "Ignore edit of " << notification_id << " with " << *type << ", because previous type is "
<< *notification.type;
@ -1683,7 +1683,7 @@ void NotificationManager::edit_notification(NotificationGroupId group_id, Notifi
}
for (auto &notification : group.pending_notifications) {
if (notification.notification_id == notification_id) {
if (notification.type->get_message_id() != type->get_message_id() ||
if (notification.type->get_object_id() != type->get_object_id() ||
notification.type->is_temporary() != type->is_temporary()) {
LOG(ERROR) << "Ignore edit of " << notification_id << " with " << *type << ", because previous type is "
<< *notification.type;
@ -1972,44 +1972,44 @@ void NotificationManager::remove_notification(NotificationGroupId group_id, Noti
promise.set_value(Unit());
}
void NotificationManager::remove_temporary_notification_by_message_id(NotificationGroupId group_id,
MessageId message_id, bool force_update,
const char *source) {
void NotificationManager::remove_temporary_notification_by_object_id(NotificationGroupId group_id,
NotificationObjectId object_id, bool force_update,
const char *source) {
if (!group_id.is_valid()) {
return;
}
VLOG(notifications) << "Remove notification for " << message_id << " in " << group_id << " from " << source;
CHECK(message_id.is_valid());
VLOG(notifications) << "Remove notification for " << object_id << " in " << group_id << " from " << source;
CHECK(object_id.is_valid());
auto group_it = get_group(group_id);
if (group_it == groups_.end()) {
return;
}
auto remove_notification_by_message_id = [&](auto &notifications) {
auto remove_notification_by_object_id = [&](auto &notifications) {
for (auto &notification : notifications) {
if (notification.type->get_message_id() == message_id) {
if (notification.type->get_object_id() == object_id) {
for (auto file_id : notification.type->get_file_ids(td_)) {
this->td_->file_manager_->delete_file(file_id, Promise<>(), "remove_temporary_notification_by_message_id");
this->td_->file_manager_->delete_file(file_id, Promise<>(), "remove_temporary_notification_by_object_id");
}
return this->remove_notification(group_id, notification.notification_id, true, force_update, Auto(),
"remove_temporary_notification_by_message_id");
"remove_temporary_notification_by_object_id");
}
}
};
remove_notification_by_message_id(group_it->second.pending_notifications);
remove_notification_by_message_id(group_it->second.notifications);
remove_notification_by_object_id(group_it->second.pending_notifications);
remove_notification_by_object_id(group_it->second.notifications);
}
void NotificationManager::remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
MessageId max_message_id, int32 new_total_count, bool force_update,
Promise<Unit> &&promise) {
NotificationObjectId max_object_id, int32 new_total_count,
bool force_update, Promise<Unit> &&promise) {
if (!group_id.is_valid()) {
return promise.set_error(Status::Error(400, "Group identifier is invalid"));
}
if (!max_notification_id.is_valid() && !max_message_id.is_valid()) {
if (!max_notification_id.is_valid() && !max_object_id.is_valid()) {
return promise.set_error(Status::Error(400, "Notification identifier is invalid"));
}
@ -2021,7 +2021,7 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
remove_temporary_notifications(group_id, "remove_notification_group");
}
VLOG(notifications) << "Remove " << group_id << " up to " << max_notification_id << " or " << max_message_id
VLOG(notifications) << "Remove " << group_id << " up to " << max_notification_id << " or " << max_object_id
<< " with new_total_count = " << new_total_count << " and force_update = " << force_update;
auto group_it = get_group_force(group_id);
@ -2040,7 +2040,7 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
case NotificationGroupType::SecretChat:
td_->messages_manager_->remove_message_notifications(
group_it->first.dialog_id, group_id, max_notification_id,
get_last_message_id_by_notification_id(group_it->second, max_notification_id));
MessageId(get_last_object_id_by_notification_id(group_it->second, max_notification_id).get()));
break;
case NotificationGroupType::Calls:
// nothing to do
@ -2055,7 +2055,7 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
for (auto it = group_it->second.pending_notifications.begin(); it != group_it->second.pending_notifications.end();
++it) {
if (it->notification_id.get() <= max_notification_id.get() ||
(max_message_id.is_valid() && it->type->get_message_id() <= max_message_id)) {
(max_object_id.is_valid() && it->type->get_object_id() <= max_object_id)) {
pending_delete_end = it + 1;
on_notification_removed(it->notification_id);
}
@ -2084,7 +2084,7 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
for (size_t pos = 0; pos < notification_delete_end; pos++) {
auto &notification = group_it->second.notifications[pos];
if (notification.notification_id.get() > max_notification_id.get() &&
(!max_message_id.is_valid() || notification.type->get_message_id() > max_message_id)) {
(!max_object_id.is_valid() || notification.type->get_object_id() > max_object_id)) {
notification_delete_end = pos;
} else {
on_notification_removed(notification.notification_id);
@ -2135,10 +2135,10 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
});
} else {
remove_added_notifications_from_pending_updates(
group_id, [max_message_id](const td_api::object_ptr<td_api::notification> &notification) {
group_id, [max_object_id](const td_api::object_ptr<td_api::notification> &notification) {
return notification->type_->get_id() == td_api::notificationTypeNewMessage::ID &&
static_cast<const td_api::notificationTypeNewMessage *>(notification->type_.get())->message_->id_ <=
max_message_id.get();
max_object_id.get();
});
}
@ -2308,17 +2308,22 @@ vector<MessageId> NotificationManager::get_notification_group_message_ids(Notifi
return {};
}
if (group_it->second.type != NotificationGroupType::Mentions &&
group_it->second.type != NotificationGroupType::Messages) {
return {};
}
vector<MessageId> message_ids;
for (auto &notification : group_it->second.notifications) {
auto message_id = notification.type->get_message_id();
if (message_id.is_valid()) {
message_ids.push_back(message_id);
auto object_id = notification.type->get_object_id();
if (object_id.is_valid()) {
message_ids.push_back(MessageId(object_id.get()));
}
}
for (auto &notification : group_it->second.pending_notifications) {
auto message_id = notification.type->get_message_id();
if (message_id.is_valid()) {
message_ids.push_back(message_id);
auto object_id = notification.type->get_object_id();
if (object_id.is_valid()) {
message_ids.push_back(MessageId(object_id.get()));
}
}

View File

@ -16,6 +16,7 @@
#include "td/telegram/NotificationGroupKey.h"
#include "td/telegram/NotificationGroupType.h"
#include "td/telegram/NotificationId.h"
#include "td/telegram/NotificationObjectId.h"
#include "td/telegram/NotificationType.h"
#include "td/telegram/Photo.h"
#include "td/telegram/td_api.h"
@ -82,11 +83,11 @@ class NotificationManager final : public Actor {
void remove_temporary_notifications(NotificationGroupId group_id, const char *source);
void remove_temporary_notification_by_message_id(NotificationGroupId group_id, MessageId message_id,
bool force_update, const char *source);
void remove_temporary_notification_by_object_id(NotificationGroupId group_id, NotificationObjectId object_id,
bool force_update, const char *source);
void remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
MessageId max_message_id, int32 new_total_count, bool force_update,
NotificationObjectId max_object_id, int32 new_total_count, bool force_update,
Promise<Unit> &&promise);
void set_notification_total_count(NotificationGroupId group_id, int32 new_total_count);
@ -238,12 +239,12 @@ class NotificationManager final : public Actor {
static NotificationId get_last_notification_id(const NotificationGroup &group);
static MessageId get_first_message_id(const NotificationGroup &group);
static NotificationObjectId get_first_object_id(const NotificationGroup &group);
static MessageId get_last_message_id(const NotificationGroup &group);
static NotificationObjectId get_last_object_id(const NotificationGroup &group);
static MessageId get_last_message_id_by_notification_id(const NotificationGroup &group,
NotificationId max_notification_id);
static NotificationObjectId get_last_object_id_by_notification_id(const NotificationGroup &group,
NotificationId max_notification_id);
static int32 get_temporary_notification_total_count(const NotificationGroup &group);

View File

@ -0,0 +1,71 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/MessageId.h"
#include "td/utils/common.h"
namespace td {
class NotificationObjectId {
int64 id = 0;
public:
NotificationObjectId() = default;
NotificationObjectId(MessageId message_id) : id(message_id.get()) {
}
static NotificationObjectId max() {
return NotificationObjectId(MessageId::max());
}
int64 get() const {
return id;
}
bool is_valid() const {
return id > 0;
}
bool operator==(const NotificationObjectId &other) const {
return id == other.id;
}
bool operator!=(const NotificationObjectId &other) const {
return id != other.id;
}
friend bool operator<(const NotificationObjectId &lhs, const NotificationObjectId &rhs) {
return lhs.id < rhs.id;
}
friend bool operator>(const NotificationObjectId &lhs, const NotificationObjectId &rhs) {
return lhs.id > rhs.id;
}
friend bool operator<=(const NotificationObjectId &lhs, const NotificationObjectId &rhs) {
return lhs.id <= rhs.id;
}
friend bool operator>=(const NotificationObjectId &lhs, const NotificationObjectId &rhs) {
return lhs.id >= rhs.id;
}
};
struct NotificationObjectIdHash {
uint32 operator()(NotificationObjectId notification_object_id) const {
return Hash<int64>()(notification_object_id.get());
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, NotificationObjectId notification_object_id) {
return string_builder << "notification object " << notification_object_id.get();
}
} // namespace td

View File

@ -34,7 +34,7 @@ class NotificationTypeMessage final : public NotificationType {
return false;
}
MessageId get_message_id() const final {
NotificationObjectId get_object_id() const final {
return message_id_;
}
@ -73,8 +73,8 @@ class NotificationTypeSecretChat final : public NotificationType {
return false;
}
MessageId get_message_id() const final {
return MessageId();
NotificationObjectId get_object_id() const final {
return NotificationObjectId();
}
vector<FileId> get_file_ids(const Td *td) const final {
@ -103,8 +103,8 @@ class NotificationTypeCall final : public NotificationType {
return false;
}
MessageId get_message_id() const final {
return MessageId::max();
NotificationObjectId get_object_id() const final {
return NotificationObjectId::max();
}
vector<FileId> get_file_ids(const Td *td) const final {
@ -135,7 +135,7 @@ class NotificationTypePushMessage final : public NotificationType {
return true;
}
MessageId get_message_id() const final {
NotificationObjectId get_object_id() const final {
return message_id_;
}

View File

@ -10,7 +10,7 @@
#include "td/telegram/DialogId.h"
#include "td/telegram/Document.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/NotificationObjectId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/td_api.h"
#include "td/telegram/UserId.h"
@ -33,7 +33,7 @@ class NotificationType {
virtual bool is_temporary() const = 0;
virtual MessageId get_message_id() const = 0;
virtual NotificationObjectId get_object_id() const = 0;
virtual vector<FileId> get_file_ids(const Td *td) const = 0;

View File

@ -96,6 +96,7 @@
#include "td/telegram/NotificationGroupId.h"
#include "td/telegram/NotificationId.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationObjectId.h"
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/NotificationSettingsScope.h"
#include "td/telegram/OptionManager.h"
@ -5406,7 +5407,7 @@ void Td::on_request(uint64 id, const td_api::removeNotificationGroup &request) {
CREATE_OK_REQUEST_PROMISE();
send_closure(notification_manager_actor_, &NotificationManager::remove_notification_group,
NotificationGroupId(request.notification_group_id_), NotificationId(request.max_notification_id_),
MessageId(), -1, true, std::move(promise));
NotificationObjectId(), -1, true, std::move(promise));
}
void Td::on_request(uint64 id, const td_api::deleteMessages &request) {