Send to NotificationManager notifications about new/edited messages.

GitOrigin-RevId: 79647054a22e1376c8a69da180ba293300468ed6
This commit is contained in:
levlam 2018-11-11 15:58:52 +03:00
parent 4240b785a0
commit 0ca9b6493d
12 changed files with 278 additions and 132 deletions

View File

@ -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

View File

@ -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<NotificationManager> notification_manager() const {
return notification_manager_;
}
void set_notification_manager(ActorId<NotificationManager> notification_manager) {
notification_manager_ = notification_manager;
}
ActorId<PasswordManager> password_manager() const {
return password_manager_;
}
@ -333,6 +341,7 @@ class Global : public ActorContext {
ActorId<FileManager> file_manager_;
ActorId<LanguagePackManager> language_pack_manager_;
ActorId<MessagesManager> messages_manager_;
ActorId<NotificationManager> notification_manager_;
ActorId<PasswordManager> password_manager_;
ActorId<SecretChatsManager> secret_chats_manager_;
ActorId<StickersManager> stickers_manager_;

View File

@ -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<Slice, int *, SliceHash> 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<td_api::LogStream> stream) {

View File

@ -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<ReplyMarkup>();
@ -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 <class StorerT>
@ -4783,8 +4805,8 @@ void MessagesManager::on_update_service_notification(tl_object_ptr<telegram_api:
bool need_update = true;
bool need_update_dialog_pos = false;
Message *m = add_message_to_dialog(d, std::move(new_message), true, &need_update, &need_update_dialog_pos,
"on_update_service_notification");
const Message *m = add_message_to_dialog(d, std::move(new_message), true, &need_update, &need_update_dialog_pos,
"on_update_service_notification");
if (m != nullptr && need_update) {
send_update_new_message(d, m);
}
@ -4838,8 +4860,8 @@ void MessagesManager::on_update_contact_registered(tl_object_ptr<telegram_api::u
bool need_update = true;
bool need_update_dialog_pos = false;
Message *m = add_message_to_dialog(d, std::move(new_message), true, &need_update, &need_update_dialog_pos,
"on_update_contact_registered");
const Message *m = add_message_to_dialog(d, std::move(new_message), true, &need_update, &need_update_dialog_pos,
"on_update_contact_registered");
if (m != nullptr && need_update) {
send_update_new_message(d, m);
}
@ -5553,6 +5575,11 @@ void MessagesManager::on_message_edited(FullMessageId full_message_id) {
if (m->forward_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<td_api::updateNewMessage>(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<SleepActor>(
"FlushPendingNewMessageNotificationsSleepActor", 5.0,
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id = d->dialog_id](Result<Unit> 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<Unit> 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<Message> *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<Message> *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<Message> *left = &message->left;
unique_ptr<Message> *right = &message->right;
unique_ptr<Message> *left = &message->left;
unique_ptr<Message> *right = &message->right;
unique_ptr<Message> 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<Message> 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) {

View File

@ -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<MessageContent> 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);

View File

@ -36,6 +36,16 @@ class NotificationGroupId {
return id == other.id;
}
template <class StorerT>
void store(StorerT &storer) const {
storer.store_int(id);
}
template <class ParserT>
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

View File

@ -36,6 +36,16 @@ class NotificationId {
return id == other.id;
}
template <class StorerT>
void store(StorerT &storer) const {
storer.store_int(id);
}
template <class ParserT>
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

View File

@ -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<int32>(G()->td_db()->get_binlog_pmc()->get("notification_id_current")));
current_notification_group_id_ =
NotificationGroupId(to_integer<int32>(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<NotificationType> 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<NotificationType> 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());
}

View File

@ -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<NotificationType> 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<NotificationType> type);
void edit_notification(NotificationId notification_id, unique_ptr<NotificationType> type);
@ -39,7 +43,14 @@ class NotificationManager {
Promise<Unit> &&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

View File

@ -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<AudiosManager>(this);
callback_queries_manager_ = make_unique<CallbackQueriesManager>(this);
documents_manager_ = make_unique<DocumentsManager>(this);
notification_manager_ = make_unique<NotificationManager>(this);
video_notes_manager_ = make_unique<VideoNotesManager>(this);
videos_manager_ = make_unique<VideosManager>(this);
voice_notes_manager_ = make_unique<VoiceNotesManager>(this);
@ -4044,6 +4045,9 @@ Status Td::init(DbKey key) {
messages_manager_ = make_unique<MessagesManager>(this, create_reference());
messages_manager_actor_ = register_actor("MessagesManager", messages_manager_.get());
G()->set_messages_manager(messages_manager_actor_.get());
notification_manager_ = make_unique<NotificationManager>(this, create_reference());
notification_manager_actor_ = register_actor("NotificationManager", notification_manager_.get());
G()->set_notification_manager(notification_manager_actor_.get());
stickers_manager_ = make_unique<StickersManager>(this, create_reference());
stickers_manager_actor_ = register_actor("StickersManager", stickers_manager_.get());
G()->set_stickers_manager(stickers_manager_actor_.get());

View File

@ -126,7 +126,6 @@ class Td final : public NetQueryCallback {
unique_ptr<AudiosManager> audios_manager_;
unique_ptr<CallbackQueriesManager> callback_queries_manager_;
unique_ptr<DocumentsManager> documents_manager_;
unique_ptr<NotificationManager> notification_manager_;
unique_ptr<VideoNotesManager> video_notes_manager_;
unique_ptr<VideosManager> videos_manager_;
unique_ptr<VoiceNotesManager> voice_notes_manager_;
@ -143,6 +142,8 @@ class Td final : public NetQueryCallback {
ActorOwn<InlineQueriesManager> inline_queries_manager_actor_;
unique_ptr<MessagesManager> messages_manager_;
ActorOwn<MessagesManager> messages_manager_actor_;
unique_ptr<NotificationManager> notification_manager_;
ActorOwn<NotificationManager> notification_manager_actor_;
unique_ptr<StickersManager> stickers_manager_;
ActorOwn<StickersManager> stickers_manager_actor_;
unique_ptr<UpdatesManager> updates_manager_;

View File

@ -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"