From 0ca9b6493d3a073cd9e30d8db07e89f465fd1345 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 11 Nov 2018 15:58:52 +0300 Subject: [PATCH] Send to NotificationManager notifications about new/edited messages. GitOrigin-RevId: 79647054a22e1376c8a69da180ba293300468ed6 --- td/generate/scheme/td_api.tl | 2 +- td/telegram/Global.h | 9 + td/telegram/Logging.cpp | 8 +- td/telegram/MessagesManager.cpp | 266 +++++++++++++++++----------- td/telegram/MessagesManager.h | 28 +-- td/telegram/NotificationGroupId.h | 12 +- td/telegram/NotificationId.h | 12 +- td/telegram/NotificationManager.cpp | 39 +++- td/telegram/NotificationManager.h | 21 ++- td/telegram/Td.cpp | 6 +- td/telegram/Td.h | 3 +- td/telegram/TdDb.h | 4 +- 12 files changed, 278 insertions(+), 132 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 26e9f50d..ecaf21f7 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3447,7 +3447,7 @@ setLogVerbosityLevel new_verbosity_level:int32 = Ok; //@description Returns current verbosity level of the internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously getLogVerbosityLevel = LogVerbosityLevel; -//@description Returns list of available TDLib internal log tags. Currently returns ["td_init", "update_file", "connections", "binlog", "proxy", "net_query", "td_requests", "dc", "files", "mtproto", "raw_mtproto", "fd", "actor", "buffer", "sqlite"] +//@description Returns list of available TDLib internal log tags. Currently returns ["td_init", "update_file", "connections", "binlog", "proxy", "net_query", "td_requests", "dc", "files", "mtproto", "raw_mtproto", "fd", "actor", "buffer", "sqlite", "notifications"] getLogTags = LogTags; //@description Sets the verbosity level for a specified TDLib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously diff --git a/td/telegram/Global.h b/td/telegram/Global.h index 834082fe..50881018 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -42,6 +42,7 @@ class LanguagePackManager; class MessagesManager; class MtprotoHeader; class NetQueryDispatcher; +class NotificationManager; class PasswordManager; class SecretChatsManager; class StateManager; @@ -189,6 +190,13 @@ class Global : public ActorContext { messages_manager_ = messages_manager; } + ActorId notification_manager() const { + return notification_manager_; + } + void set_notification_manager(ActorId notification_manager) { + notification_manager_ = notification_manager; + } + ActorId password_manager() const { return password_manager_; } @@ -333,6 +341,7 @@ class Global : public ActorContext { ActorId file_manager_; ActorId language_pack_manager_; ActorId messages_manager_; + ActorId notification_manager_; ActorId password_manager_; ActorId secret_chats_manager_; ActorId stickers_manager_; diff --git a/td/telegram/Logging.cpp b/td/telegram/Logging.cpp index ece3256d..9bea786a 100644 --- a/td/telegram/Logging.cpp +++ b/td/telegram/Logging.cpp @@ -8,6 +8,7 @@ #include "td/telegram/files/FileManager.h" #include "td/telegram/net/ConnectionCreator.h" +#include "td/telegram/NotificationManager.h" #include "td/telegram/Td.h" #include "tddb/td/db/binlog/BinlogEvent.h" @@ -31,9 +32,10 @@ static NullLog null_log; #define ADD_TAG(tag) \ { #tag, &VERBOSITY_NAME(tag) } static const std::unordered_map log_tags{ - ADD_TAG(td_init), ADD_TAG(update_file), ADD_TAG(connections), ADD_TAG(binlog), ADD_TAG(proxy), - ADD_TAG(net_query), ADD_TAG(td_requests), ADD_TAG(dc), ADD_TAG(files), ADD_TAG(mtproto), - ADD_TAG(raw_mtproto), ADD_TAG(fd), ADD_TAG(actor), ADD_TAG(buffer), ADD_TAG(sqlite)}; + ADD_TAG(td_init), ADD_TAG(update_file), ADD_TAG(connections), ADD_TAG(binlog), + ADD_TAG(proxy), ADD_TAG(net_query), ADD_TAG(td_requests), ADD_TAG(dc), + ADD_TAG(files), ADD_TAG(mtproto), ADD_TAG(raw_mtproto), ADD_TAG(fd), + ADD_TAG(actor), ADD_TAG(buffer), ADD_TAG(sqlite), ADD_TAG(notifications)}; #undef ADD_TAG Status Logging::set_current_stream(td_api::object_ptr stream) { diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index b063331e..728a80d3 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -29,7 +29,9 @@ #include "td/telegram/net/DcId.h" #include "td/telegram/net/NetActor.h" #include "td/telegram/net/NetQuery.h" +#include "td/telegram/NotificationManager.h" #include "td/telegram/NotificationSettings.hpp" +#include "td/telegram/NotificationType.h" #include "td/telegram/Payments.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.hpp" @@ -3538,6 +3540,7 @@ void MessagesManager::Message::store(StorerT &storer) const { is_forwarded && (forward_info->from_dialog_id.is_valid() || forward_info->from_message_id.is_valid()); bool has_send_date = message_id.is_yet_unsent() && send_date != 0; bool has_flags2 = true; + bool has_notification_id = notification_id.is_valid(); BEGIN_STORE_FLAGS(); STORE_FLAG(is_channel_post); STORE_FLAG(is_outgoing); @@ -3572,6 +3575,7 @@ void MessagesManager::Message::store(StorerT &storer) const { END_STORE_FLAGS(); if (has_flags2) { BEGIN_STORE_FLAGS(); + STORE_FLAG(has_notification_id); END_STORE_FLAGS(); } @@ -3631,6 +3635,9 @@ void MessagesManager::Message::store(StorerT &storer) const { if (has_media_album_id) { store(media_album_id, storer); } + if (has_notification_id) { + store(notification_id, storer); + } store_message_content(content.get(), storer); if (has_reply_markup) { store(*reply_markup, storer); @@ -3657,6 +3664,7 @@ void MessagesManager::Message::parse(ParserT &parser) { bool has_forward_from; bool has_send_date; bool has_flags2; + bool has_notification_id = false; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_channel_post); PARSE_FLAG(is_outgoing); @@ -3691,6 +3699,7 @@ void MessagesManager::Message::parse(ParserT &parser) { END_PARSE_FLAGS(); if (has_flags2) { BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_notification_id); END_PARSE_FLAGS(); } @@ -3758,6 +3767,9 @@ void MessagesManager::Message::parse(ParserT &parser) { if (has_media_album_id) { parse(media_album_id, parser); } + if (has_notification_id) { + parse(notification_id, parser); + } parse_message_content(content, parser); if (has_reply_markup) { reply_markup = make_unique(); @@ -3788,6 +3800,7 @@ void MessagesManager::Dialog::store(StorerT &storer) const { bool has_deleted_last_message = delete_last_message_date > 0; bool has_last_clear_history_message_id = last_clear_history_message_id.is_valid(); bool has_last_database_message_id = !has_last_database_message && last_database_message_id.is_valid(); + bool has_message_notification_group_id = message_notification_group_id.is_valid(); BEGIN_STORE_FLAGS(); STORE_FLAG(has_draft_message); STORE_FLAG(has_last_database_message); @@ -3812,6 +3825,7 @@ void MessagesManager::Dialog::store(StorerT &storer) const { STORE_FLAG(has_last_database_message_id); STORE_FLAG(need_repair_server_unread_count); STORE_FLAG(is_marked_as_unread); + STORE_FLAG(has_message_notification_group_id); // 23 END_STORE_FLAGS(); store(dialog_id, storer); // must be stored at offset 4 @@ -3870,6 +3884,9 @@ void MessagesManager::Dialog::store(StorerT &storer) const { if (has_last_database_message_id) { store(last_database_message_id, storer); } + if (has_message_notification_group_id) { + store(message_notification_group_id, storer); + } } // do not forget to resolve dialog dependencies including dependencies of last_message @@ -3889,6 +3906,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) { bool has_deleted_last_message; bool has_last_clear_history_message_id; bool has_last_database_message_id; + bool has_message_notification_group_id; BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_draft_message); PARSE_FLAG(has_last_database_message); @@ -3912,7 +3930,8 @@ void MessagesManager::Dialog::parse(ParserT &parser) { PARSE_FLAG(has_contact_registered_message); PARSE_FLAG(has_last_database_message_id); PARSE_FLAG(need_repair_server_unread_count); - PARSE_FLAG(is_marked_as_unread); // 22 + PARSE_FLAG(is_marked_as_unread); + PARSE_FLAG(has_message_notification_group_id); END_PARSE_FLAGS(); parse(dialog_id, parser); // must be stored at offset 4 @@ -3995,6 +4014,9 @@ void MessagesManager::Dialog::parse(ParserT &parser) { if (has_last_database_message_id) { parse(last_database_message_id, parser); } + if (has_message_notification_group_id) { + parse(message_notification_group_id, parser); + } } template @@ -4783,8 +4805,8 @@ void MessagesManager::on_update_service_notification(tl_object_ptrforward_info == nullptr && (m->is_outgoing || dialog_id == get_my_dialog_id())) { update_used_hashtags(dialog_id, m); } + + if (m->notification_id.is_valid()) { + send_closure_later(G()->notification_manager(), &NotificationManager::edit_notification, m->notification_id, + create_new_message_notification(m->message_id)); + } } } @@ -9512,8 +9539,8 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f new_message->have_next = true; } - Message *m = add_message_to_dialog(dialog_id, std::move(new_message), from_update, &need_update, - &need_update_dialog_pos, source); + const Message *m = add_message_to_dialog(dialog_id, std::move(new_message), from_update, &need_update, + &need_update_dialog_pos, source); Dialog *d = get_dialog(dialog_id); if (m == nullptr) { if (need_update_dialog_pos && d != nullptr) { @@ -17323,35 +17350,47 @@ void MessagesManager::on_dialog_updated(DialogId dialog_id, const char *source) } } -void MessagesManager::send_update_new_message(Dialog *d, const Message *m) { +void MessagesManager::send_update_new_message(const Dialog *d, const Message *m) { CHECK(d != nullptr); CHECK(m != nullptr); LOG(INFO) << "Send updateNewMessage for " << m->message_id << " in " << d->dialog_id; send_closure(G()->td(), &Td::send_update, make_tl_object(get_message_object(d->dialog_id, m))); - - add_new_message_notification(d, m, false); } -void MessagesManager::add_new_message_notification(Dialog *d, const Message *m, bool force) { +NotificationGroupId MessagesManager::get_dialog_message_notification_group_id(Dialog *d) { + if (!d->message_notification_group_id.is_valid()) { + d->message_notification_group_id = td_->notification_manager_->get_next_notification_group_id(); + VLOG(notifications) << "Assign " << d->message_notification_group_id << " to " << d->dialog_id; + on_dialog_updated(d->dialog_id, "get_dialog_message_notification_group_id"); + } + + CHECK(d->message_notification_group_id.is_valid()); + return d->message_notification_group_id; +} + +void MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool force) { CHECK(d != nullptr); CHECK(m != nullptr); - if (m->disable_notification || m->is_outgoing || d->dialog_id == get_my_dialog_id() || td_->auth_manager_->is_bot()) { + CHECK(!m->notification_id.is_valid()); + if (m->is_outgoing || d->dialog_id == get_my_dialog_id() || td_->auth_manager_->is_bot()) { return; } if (m->message_id.get() <= d->last_read_inbox_message_id.get()) { - LOG(INFO) << "Disable notification for read " << m->message_id << " in " << d->dialog_id; + VLOG(notifications) << "Disable notification for read " << m->message_id << " in " << d->dialog_id; return; } - if (d->dialog_id.get_type() == DialogType::Channel && - !td_->contacts_manager_->get_channel_status(d->dialog_id.get_channel_id()).is_member()) { - return; + if (d->dialog_id.get_type() == DialogType::Channel) { + if (!td_->contacts_manager_->get_channel_status(d->dialog_id.get_channel_id()).is_member() || + m->date < td_->contacts_manager_->get_channel_date(d->dialog_id.get_channel_id())) { + return; + } } - LOG(INFO) << "Trying to " << (force ? "forcely " : "") << "add new message notification for " << m->message_id - << " in " << d->dialog_id; + VLOG(notifications) << "Trying to " << (force ? "forcely " : "") << "add new message notification for " + << m->message_id << " in " << d->dialog_id; DialogId settings_dialog_id = d->dialog_id; Dialog *settings_dialog = d; @@ -17365,6 +17404,7 @@ void MessagesManager::add_new_message_notification(Dialog *d, const Message *m, int32 mute_until; std::tie(have_settings, mute_until) = get_dialog_mute_until(settings_dialog_id, settings_dialog); if (mute_until > G()->unix_time()) { + VLOG(notifications) << "Disable notification, because " << settings_dialog_id << " is muted"; return; } @@ -17375,14 +17415,15 @@ void MessagesManager::add_new_message_notification(Dialog *d, const Message *m, create_actor( "FlushPendingNewMessageNotificationsSleepActor", 5.0, PromiseCreator::lambda([actor_id = actor_id(this), dialog_id = d->dialog_id](Result result) { - LOG(INFO) << "Flush pending notifications in " << dialog_id << " by timeout"; + VLOG(notifications) << "Flush pending notifications in " << dialog_id << " by timeout"; send_closure(actor_id, &MessagesManager::flush_pending_new_message_notifications, dialog_id); })) .release(); } d->pending_new_message_notifications.push_back(m->message_id); auto promise = PromiseCreator::lambda([actor_id = actor_id(this), dialog_id = d->dialog_id](Result result) { - LOG(INFO) << "Flush pending notifications in " << dialog_id << " because of received notification settings"; + VLOG(notifications) << "Flush pending notifications in " << dialog_id + << " because of received notification settings"; send_closure(actor_id, &MessagesManager::flush_pending_new_message_notifications, dialog_id); }); if (settings_dialog == nullptr && have_input_peer(settings_dialog_id, AccessRights::Read)) { @@ -17400,7 +17441,11 @@ void MessagesManager::add_new_message_notification(Dialog *d, const Message *m, LOG_IF(WARNING, !have_settings) << "Have no notification settings for " << settings_dialog_id << ", but forced to send notification about " << m->message_id << " in " << d->dialog_id; - // TODO + m->notification_id = td_->notification_manager_->get_next_notification_id(); + VLOG(notifications) << "Assign " << m->notification_id << " to " << m->message_id << " in " << d->dialog_id; + send_closure_later(G()->notification_manager(), &NotificationManager::add_notification, + get_dialog_message_notification_group_id(d), d->dialog_id, settings_dialog_id, + m->disable_notification, m->notification_id, create_new_message_notification(m->message_id)); } void MessagesManager::flush_pending_new_message_notifications(DialogId dialog_id) { @@ -19892,46 +19937,49 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq cancel_user_dialog_action(dialog_id, message.get()); } - unique_ptr *v = &d->messages; - while (*v != nullptr && (*v)->random_y >= message->random_y) { - if ((*v)->message_id.get() < message_id.get()) { - v = &(*v)->right; - } else if ((*v)->message_id == message_id) { - LOG(INFO) << "Adding already existing " << message_id << " in " << dialog_id << " from " << source; - if (*need_update) { - *need_update = false; - if (!G()->parameters().use_message_db) { - LOG(ERROR) << "Receive again " << (message->is_outgoing ? "outgoing" : "incoming") - << (message->forward_info == nullptr ? " not" : "") << " forwarded " << message_id - << " with content of type " << message_content_type << " in " << dialog_id << " from " << source - << ", current last new is " << d->last_new_message_id << ", last is " << d->last_message_id << ". " - << td_->updates_manager_->get_state(); - dump_debug_message_op(d, 1); + { + // TODO function + unique_ptr *v = &d->messages; + while (*v != nullptr && (*v)->random_y >= message->random_y) { + if ((*v)->message_id.get() < message_id.get()) { + v = &(*v)->right; + } else if ((*v)->message_id == message_id) { + LOG(INFO) << "Adding already existing " << message_id << " in " << dialog_id << " from " << source; + if (*need_update) { + *need_update = false; + if (!G()->parameters().use_message_db) { + LOG(ERROR) << "Receive again " << (message->is_outgoing ? "outgoing" : "incoming") + << (message->forward_info == nullptr ? " not" : "") << " forwarded " << message_id + << " with content of type " << message_content_type << " in " << dialog_id << " from " << source + << ", current last new is " << d->last_new_message_id << ", last is " << d->last_message_id + << ". " << td_->updates_manager_->get_state(); + dump_debug_message_op(d, 1); + } } - } - if (auto_attach) { - CHECK(message->have_previous); - CHECK(message->have_next); - message->have_previous = false; - message->have_next = false; - } - if (!message->from_database) { - const int32 INDEX_MASK_MASK = ~search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); - auto old_index_mask = get_message_index_mask(dialog_id, v->get()) & INDEX_MASK_MASK; - bool was_deleted = delete_active_live_location(dialog_id, v->get()); - update_message(d, *v, std::move(message), true, need_update_dialog_pos); - auto new_index_mask = get_message_index_mask(dialog_id, v->get()) & INDEX_MASK_MASK; - if (was_deleted) { - try_add_active_live_location(dialog_id, v->get()); + if (auto_attach) { + CHECK(message->have_previous); + CHECK(message->have_next); + message->have_previous = false; + message->have_next = false; } - if (old_index_mask != new_index_mask) { - update_message_count_by_index(d, -1, old_index_mask & ~new_index_mask); - update_message_count_by_index(d, +1, new_index_mask & ~old_index_mask); + if (!message->from_database) { + const int32 INDEX_MASK_MASK = ~search_messages_filter_index_mask(SearchMessagesFilter::UnreadMention); + auto old_index_mask = get_message_index_mask(dialog_id, v->get()) & INDEX_MASK_MASK; + bool was_deleted = delete_active_live_location(dialog_id, v->get()); + update_message(d, *v, std::move(message), true, need_update_dialog_pos); + auto new_index_mask = get_message_index_mask(dialog_id, v->get()) & INDEX_MASK_MASK; + if (was_deleted) { + try_add_active_live_location(dialog_id, v->get()); + } + if (old_index_mask != new_index_mask) { + update_message_count_by_index(d, -1, old_index_mask & ~new_index_mask); + update_message_count_by_index(d, +1, new_index_mask & ~old_index_mask); + } } + return v->get(); + } else { + v = &(*v)->left; } - return v->get(); - } else { - v = &(*v)->left; } } @@ -20151,11 +20199,17 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } } } - if (!message->from_database && !message_id.is_yet_unsent()) { - add_message_to_database(d, message.get(), "add_message_to_dialog"); + + if (*need_update) { + add_new_message_notification(d, message.get(), false); } - if (!is_attached && !message->have_next && !message->have_previous) { + const Message *m = message.get(); + if (!m->from_database && !message_id.is_yet_unsent()) { + add_message_to_database(d, m, "add_message_to_dialog"); + } + + if (!is_attached && !m->have_next && !m->have_previous) { MessagesIterator it(d, message_id); if (*it != nullptr && (*it)->have_next) { // need to drop a connection between messages @@ -20181,7 +20235,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } if (!td_->auth_manager_->is_bot() && from_update && d->reply_markup_message_id != MessageId()) { - auto deleted_user_id = get_message_content_deleted_user_id(message->content.get()); + auto deleted_user_id = get_message_content_deleted_user_id(m->content.get()); if (deleted_user_id.is_valid() && td_->contacts_manager_->is_user_bot(deleted_user_id)) { const Message *old_message = get_message_force(d, d->reply_markup_message_id); if (old_message == nullptr || old_message->sender_user_id == deleted_user_id) { @@ -20196,40 +20250,40 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq } if (from_update && message_id.is_server() && dialog_id.get_type() == DialogType::Channel) { - int32 new_participant_count = get_message_content_new_participant_count(message->content.get()); + int32 new_participant_count = get_message_content_new_participant_count(m->content.get()); if (new_participant_count != 0) { td_->contacts_manager_->speculative_add_channel_participants(dialog_id.get_channel_id(), new_participant_count, - message->sender_user_id == my_user_id); + m->sender_user_id == my_user_id); } - auto pinned_message_id = get_message_content_pinned_message_id(message->content.get()); + auto pinned_message_id = get_message_content_pinned_message_id(m->content.get()); if (pinned_message_id.is_valid()) { td_->contacts_manager_->on_update_channel_pinned_message(dialog_id.get_channel_id(), pinned_message_id); } } - if (!td_->auth_manager_->is_bot() && from_update && message->forward_info == nullptr && - (message->is_outgoing || dialog_id == my_dialog_id)) { + if (!td_->auth_manager_->is_bot() && from_update && m->forward_info == nullptr && + (m->is_outgoing || dialog_id == my_dialog_id)) { switch (message_content_type) { case MessageContentType::Animation: if (dialog_id.get_type() != DialogType::SecretChat) { - td_->animations_manager_->add_saved_animation_by_id(get_message_content_file_id(message->content.get())); + td_->animations_manager_->add_saved_animation_by_id(get_message_content_file_id(m->content.get())); } break; case MessageContentType::Sticker: if (dialog_id.get_type() != DialogType::SecretChat) { - td_->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_file_id(message->content.get())); + td_->stickers_manager_->add_recent_sticker_by_id(false, get_message_content_file_id(m->content.get())); } break; default: - update_used_hashtags(dialog_id, message.get()); + update_used_hashtags(dialog_id, m); break; } } if (!td_->auth_manager_->is_bot() && from_update && message_id.is_server() && - (message->is_outgoing || dialog_id == my_dialog_id) && dialog_id.get_type() != DialogType::SecretChat) { - if (message->via_bot_user_id.is_valid() && message->forward_info == nullptr) { + (m->is_outgoing || dialog_id == my_dialog_id) && dialog_id.get_type() != DialogType::SecretChat) { + if (m->via_bot_user_id.is_valid() && m->forward_info == nullptr) { // forwarded game messages can't be distinguished from sent via bot game messages, so increase rating anyway send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, TopDialogCategory::BotInline, - DialogId(message->via_bot_user_id), message->date); + DialogId(m->via_bot_user_id), m->date); } TopDialogCategory category = TopDialogCategory::Size; @@ -20266,48 +20320,52 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq UNREACHABLE(); } if (category != TopDialogCategory::Size) { - send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, message->date); + send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, m->date); } } - // TODO function - v = &d->messages; - while (*v != nullptr && (*v)->random_y >= message->random_y) { - if ((*v)->message_id.get() < message_id.get()) { - v = &(*v)->right; - } else if ((*v)->message_id == message_id) { - UNREACHABLE(); - } else { - v = &(*v)->left; + Message *result_message = nullptr; + { + // TODO function + auto v = &d->messages; + while (*v != nullptr && (*v)->random_y >= m->random_y) { + if ((*v)->message_id.get() < message_id.get()) { + v = &(*v)->right; + } else if ((*v)->message_id == message_id) { + UNREACHABLE(); + } else { + v = &(*v)->left; + } } - } - unique_ptr *left = &message->left; - unique_ptr *right = &message->right; + unique_ptr *left = &message->left; + unique_ptr *right = &message->right; - unique_ptr cur = std::move(*v); - while (cur != nullptr) { - if (cur->message_id.get() < message_id.get()) { - *left = std::move(cur); - left = &((*left)->right); - cur = std::move(*left); - } else { - *right = std::move(cur); - right = &((*right)->left); - cur = std::move(*right); + unique_ptr cur = std::move(*v); + while (cur != nullptr) { + if (cur->message_id.get() < message_id.get()) { + *left = std::move(cur); + left = &((*left)->right); + cur = std::move(*left); + } else { + *right = std::move(cur); + right = &((*right)->left); + cur = std::move(*right); + } } + CHECK(*left == nullptr); + CHECK(*right == nullptr); + *v = std::move(message); + result_message = v->get(); } - CHECK(*left == nullptr); - CHECK(*right == nullptr); - *v = std::move(message); - + CHECK(result_message != nullptr); CHECK(d->messages != nullptr); if (!is_attached) { - if ((*v)->have_next) { - CHECK(!(*v)->have_previous); + if (m->have_next) { + CHECK(!m->have_previous); attach_message_to_next(d, message_id, source); - } else if ((*v)->have_previous) { + } else if (m->have_previous) { attach_message_to_previous(d, message_id, source); } } @@ -20321,14 +20379,14 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq // nothing to do break; case DialogType::SecretChat: - add_random_id_to_message_id_correspondence(d, (*v)->random_id, message_id); + add_random_id_to_message_id_correspondence(d, m->random_id, message_id); break; case DialogType::None: default: UNREACHABLE(); } - return v->get(); + return result_message; } void MessagesManager::on_message_changed(const Dialog *d, const Message *m, const char *source) { diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 6ff5b8e0..86781202 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -10,14 +10,6 @@ #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" -#include "td/actor/actor.h" -#include "td/actor/MultiPromise.h" -#include "td/actor/PromiseFuture.h" -#include "td/actor/SignalSlot.h" -#include "td/actor/Timeout.h" - -#include "td/db/binlog/BinlogEvent.h" - #include "td/telegram/AccessRights.h" #include "td/telegram/ChannelId.h" #include "td/telegram/Dependencies.h" @@ -31,12 +23,22 @@ #include "td/telegram/MessageId.h" #include "td/telegram/MessagesDb.h" #include "td/telegram/net/NetQuery.h" +#include "td/telegram/NotificationGroupId.h" +#include "td/telegram/NotificationId.h" #include "td/telegram/NotificationSettings.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/SecretChatId.h" #include "td/telegram/SecretInputMedia.h" #include "td/telegram/UserId.h" +#include "td/db/binlog/BinlogEvent.h" + +#include "td/actor/actor.h" +#include "td/actor/MultiPromise.h" +#include "td/actor/PromiseFuture.h" +#include "td/actor/SignalSlot.h" +#include "td/actor/Timeout.h" + #include "td/utils/buffer.h" #include "td/utils/ChangesProcessor.h" #include "td/utils/common.h" @@ -782,6 +784,8 @@ class MessagesManager : public Actor { bool have_next = false; bool from_database = false; + NotificationId notification_id; + int32 views = 0; int32 ttl = 0; @@ -862,6 +866,8 @@ class MessagesManager : public Actor { MessageId max_added_message_id; + NotificationGroupId message_notification_group_id; + bool has_contact_registered_message = false; bool is_last_message_deleted_locally = false; @@ -1444,9 +1450,11 @@ class MessagesManager : public Actor { bool update_message_content(DialogId dialog_id, Message *old_message, unique_ptr new_content, bool need_send_update_message_content, bool need_merge_files); - void send_update_new_message(Dialog *d, const Message *m); + void send_update_new_message(const Dialog *d, const Message *m); - void add_new_message_notification(Dialog *d, const Message *m, bool force); + NotificationGroupId get_dialog_message_notification_group_id(Dialog *d); + + void add_new_message_notification(Dialog *d, Message *m, bool force); void flush_pending_new_message_notifications(DialogId dialog_id); diff --git a/td/telegram/NotificationGroupId.h b/td/telegram/NotificationGroupId.h index b5f1c2ad..2b091a03 100644 --- a/td/telegram/NotificationGroupId.h +++ b/td/telegram/NotificationGroupId.h @@ -36,6 +36,16 @@ class NotificationGroupId { return id == other.id; } + template + void store(StorerT &storer) const { + storer.store_int(id); + } + + template + void parse(ParserT &parser) { + id = parser.fetch_int(); + } + private: int32 id{0}; }; @@ -47,7 +57,7 @@ struct NotificationGroupIdHash { }; inline StringBuilder &operator<<(StringBuilder &sb, const NotificationGroupId group_id) { - return sb << "NotificationGroup(" << group_id.get() << ")"; + return sb << "notification group " << group_id.get(); } } // namespace td diff --git a/td/telegram/NotificationId.h b/td/telegram/NotificationId.h index bdd95545..a2712daf 100644 --- a/td/telegram/NotificationId.h +++ b/td/telegram/NotificationId.h @@ -36,6 +36,16 @@ class NotificationId { return id == other.id; } + template + void store(StorerT &storer) const { + storer.store_int(id); + } + + template + void parse(ParserT &parser) { + id = parser.fetch_int(); + } + private: int32 id{0}; }; @@ -47,7 +57,7 @@ struct NotificationIdHash { }; inline StringBuilder &operator<<(StringBuilder &sb, const NotificationId notification_id) { - return sb << "Notification(" << notification_id.get() << ")"; + return sb << "notification " << notification_id.get(); } } // namespace td diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 5ab07dc8..4dd72da6 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -6,23 +6,52 @@ // #include "td/telegram/NotificationManager.h" +#include "td/telegram/Global.h" #include "td/telegram/Td.h" +#include "td/telegram/TdDb.h" namespace td { -NotificationManager::NotificationManager(Td *td) : td_(td) { +int VERBOSITY_NAME(notifications) = VERBOSITY_NAME(WARNING); + +NotificationManager::NotificationManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { +} + +void NotificationManager::start_up() { + current_notification_id_ = + NotificationId(to_integer(G()->td_db()->get_binlog_pmc()->get("notification_id_current"))); + current_notification_group_id_ = + NotificationGroupId(to_integer(G()->td_db()->get_binlog_pmc()->get("notification_group_id_current"))); +} + +void NotificationManager::tear_down() { + parent_.reset(); } NotificationId NotificationManager::get_next_notification_id() { - return NotificationId(); + current_notification_id_ = NotificationId(current_notification_id_.get() % 0x7FFFFFFF + 1); + G()->td_db()->get_binlog_pmc()->set("notification_id_current", to_string(current_notification_id_.get())); + return current_notification_id_; } -void NotificationManager::add_notification(NotificationGroupId group_id, int32 total_count, DialogId dialog_id, +NotificationGroupId NotificationManager::get_next_notification_group_id() { + current_notification_group_id_ = NotificationGroupId(current_notification_group_id_.get() % 0x7FFFFFFF + 1); + G()->td_db()->get_binlog_pmc()->set("notification_group_id_current", to_string(current_notification_group_id_.get())); + return current_notification_group_id_; +} + +void NotificationManager::add_notification(NotificationGroupId group_id, DialogId dialog_id, DialogId notification_settings_dialog_id, bool silent, NotificationId notification_id, unique_ptr type) { + CHECK(type != nullptr); + VLOG(notifications) << "Add " << notification_id << " to " << group_id << " in " << dialog_id + << " with settings from " << notification_settings_dialog_id + << (silent ? " silent" : " with sound") << ": " << *type; + // TODO total_count++; } void NotificationManager::edit_notification(NotificationId notification_id, unique_ptr type) { + VLOG(notifications) << "Edit " << notification_id << ": " << *type; } void NotificationManager::delete_notification(NotificationId notification_id) { @@ -32,6 +61,8 @@ void NotificationManager::remove_notification(NotificationId notification_id, Pr if (!notification_id.is_valid()) { return promise.set_error(Status::Error(400, "Notification identifier is invalid")); } + + // TODO update total_count promise.set_value(Unit()); } @@ -43,6 +74,8 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id if (!max_notification_id.is_valid()) { return promise.set_error(Status::Error(400, "Notification identifier is invalid")); } + + // TODO update total_count promise.set_value(Unit()); } diff --git a/td/telegram/NotificationManager.h b/td/telegram/NotificationManager.h index 871b0b6c..fe6f5f95 100644 --- a/td/telegram/NotificationManager.h +++ b/td/telegram/NotificationManager.h @@ -11,23 +11,27 @@ #include "td/telegram/NotificationId.h" #include "td/telegram/NotificationType.h" +#include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/utils/common.h" namespace td { +extern int VERBOSITY_NAME(notifications); + class Td; -class NotificationManager { +class NotificationManager : public Actor { public: - explicit NotificationManager(Td *td); + NotificationManager(Td *td, ActorShared<> parent); NotificationId get_next_notification_id(); - void add_notification(NotificationGroupId group_id, int32 total_count, DialogId dialog_id, - DialogId notification_settings_dialog_id, bool silent, NotificationId notification_id, - unique_ptr type); + NotificationGroupId get_next_notification_group_id(); + + void add_notification(NotificationGroupId group_id, DialogId dialog_id, DialogId notification_settings_dialog_id, + bool silent, NotificationId notification_id, unique_ptr type); void edit_notification(NotificationId notification_id, unique_ptr type); @@ -39,7 +43,14 @@ class NotificationManager { Promise &&promise); private: + void start_up() override; + void tear_down() override; + + NotificationId current_notification_id_; + NotificationGroupId current_notification_group_id_; + Td *td_; + ActorShared<> parent_; }; } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f3dda4f2..a63fd507 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3769,6 +3769,8 @@ void Td::clear() { LOG(DEBUG) << "InlineQueriesManager actor was cleared " << timer; messages_manager_actor_.reset(); // TODO: Stop silent LOG(DEBUG) << "MessagesManager actor was cleared " << timer; + notification_manager_actor_.reset(); + LOG(DEBUG) << "NotificationManager actor was cleared " << timer; stickers_manager_actor_.reset(); LOG(DEBUG) << "StickersManager actor was cleared " << timer; updates_manager_actor_.reset(); @@ -4028,7 +4030,6 @@ Status Td::init(DbKey key) { audios_manager_ = make_unique(this); callback_queries_manager_ = make_unique(this); documents_manager_ = make_unique(this); - notification_manager_ = make_unique(this); video_notes_manager_ = make_unique(this); videos_manager_ = make_unique(this); voice_notes_manager_ = make_unique(this); @@ -4044,6 +4045,9 @@ Status Td::init(DbKey key) { messages_manager_ = make_unique(this, create_reference()); messages_manager_actor_ = register_actor("MessagesManager", messages_manager_.get()); G()->set_messages_manager(messages_manager_actor_.get()); + notification_manager_ = make_unique(this, create_reference()); + notification_manager_actor_ = register_actor("NotificationManager", notification_manager_.get()); + G()->set_notification_manager(notification_manager_actor_.get()); stickers_manager_ = make_unique(this, create_reference()); stickers_manager_actor_ = register_actor("StickersManager", stickers_manager_.get()); G()->set_stickers_manager(stickers_manager_actor_.get()); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 2cc31fdb..bf2f2043 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -126,7 +126,6 @@ class Td final : public NetQueryCallback { unique_ptr audios_manager_; unique_ptr callback_queries_manager_; unique_ptr documents_manager_; - unique_ptr notification_manager_; unique_ptr video_notes_manager_; unique_ptr videos_manager_; unique_ptr voice_notes_manager_; @@ -143,6 +142,8 @@ class Td final : public NetQueryCallback { ActorOwn inline_queries_manager_actor_; unique_ptr messages_manager_; ActorOwn messages_manager_actor_; + unique_ptr notification_manager_; + ActorOwn notification_manager_actor_; unique_ptr stickers_manager_; ActorOwn stickers_manager_actor_; unique_ptr updates_manager_; diff --git a/td/telegram/TdDb.h b/td/telegram/TdDb.h index 69fd1c36..55901343 100644 --- a/td/telegram/TdDb.h +++ b/td/telegram/TdDb.h @@ -6,7 +6,7 @@ // #pragma once -#include "td/actor/PromiseFuture.h" +#include "td/telegram/TdParameters.h" #include "td/db/binlog/Binlog.h" #include "td/db/binlog/BinlogEvent.h" @@ -15,7 +15,7 @@ #include "td/db/DbKey.h" #include "td/db/Pmc.h" -#include "td/telegram/TdParameters.h" +#include "td/actor/PromiseFuture.h" #include "td/utils/Slice.h" #include "td/utils/Status.h"