Move scope notification settings tp NotificationSettingsManager.

This commit is contained in:
levlam 2022-04-11 12:45:52 +03:00
parent 61014ce5b0
commit 9fd72e86d0
8 changed files with 566 additions and 470 deletions

View File

@ -5871,13 +5871,8 @@ void MessagesManager::on_dialog_unmute_timeout_callback(void *messages_manager_p
}
auto messages_manager = static_cast<MessagesManager *>(messages_manager_ptr);
if (1 <= dialog_id_int && dialog_id_int <= 3) {
send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_scope_unmute,
static_cast<NotificationSettingsScope>(dialog_id_int - 1));
} else {
send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_dialog_unmute,
DialogId(dialog_id_int));
}
send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_dialog_unmute,
DialogId(dialog_id_int));
}
void MessagesManager::on_pending_send_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) {
@ -7828,26 +7823,6 @@ void MessagesManager::on_message_edited(FullMessageId full_message_id, int32 pts
update_used_hashtags(dialog_id, m);
}
string MessagesManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) {
switch (scope) {
case NotificationSettingsScope::Private:
return "nsfpc";
case NotificationSettingsScope::Group:
return "nsfgc";
case NotificationSettingsScope::Channel:
return "nsfcc";
default:
UNREACHABLE();
return "";
}
}
void MessagesManager::save_scope_notification_settings(NotificationSettingsScope scope,
const ScopeNotificationSettings &new_settings) {
string key = get_notification_settings_scope_database_key(scope);
G()->td_db()->get_binlog_pmc()->set(key, log_event_store(new_settings).as_slice().str());
}
bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id,
DialogNotificationSettings *current_settings,
const DialogNotificationSettings &new_settings) {
@ -7913,67 +7888,6 @@ bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id,
return need_update_server;
}
bool MessagesManager::update_scope_notification_settings(NotificationSettingsScope scope,
ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings) {
if (td_->auth_manager_->is_bot()) {
// just in case
return false;
}
bool need_update_server = current_settings->mute_until != new_settings.mute_until ||
current_settings->sound != new_settings.sound ||
current_settings->show_preview != new_settings.show_preview;
bool need_update_local =
current_settings->disable_pinned_message_notifications != new_settings.disable_pinned_message_notifications ||
current_settings->disable_mention_notifications != new_settings.disable_mention_notifications;
bool was_inited = current_settings->is_synchronized;
bool is_inited = new_settings.is_synchronized;
if (was_inited && !is_inited) {
return false; // just in case
}
bool is_changed = need_update_server || need_update_local || was_inited != is_inited;
if (is_changed) {
save_scope_notification_settings(scope, new_settings);
VLOG(notifications) << "Update notification settings in " << scope << " from " << *current_settings << " to "
<< new_settings;
update_scope_unmute_timeout(scope, current_settings->mute_until, new_settings.mute_until);
if (!current_settings->disable_pinned_message_notifications && new_settings.disable_pinned_message_notifications) {
VLOG(notifications) << "Remove pinned message notifications in " << scope;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->notification_settings.use_default_disable_pinned_message_notifications &&
d->mention_notification_group.group_id.is_valid() && d->pinned_message_notification_message_id.is_valid() &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
remove_dialog_pinned_message_notification(d, "update_scope_notification_settings");
}
}
}
if (current_settings->disable_mention_notifications != new_settings.disable_mention_notifications) {
VLOG(notifications) << "Remove mention notifications in " << scope;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->notification_settings.use_default_disable_mention_notifications &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
if (current_settings->disable_mention_notifications) {
update_dialog_mention_notification_count(d);
} else {
remove_dialog_mention_notifications(d);
}
}
}
}
*current_settings = new_settings;
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
}
return need_update_server;
}
void MessagesManager::schedule_dialog_unmute(DialogId dialog_id, bool use_default, int32 mute_until) {
auto now = G()->unix_time_cached();
if (!use_default && mute_until >= now && mute_until < now + 366 * 86400) {
@ -7998,8 +7912,10 @@ void MessagesManager::update_dialog_unmute_timeout(Dialog *d, bool &old_use_defa
schedule_dialog_unmute(d->dialog_id, new_use_default, new_mute_until);
bool was_muted = (old_use_default ? get_scope_mute_until(d->dialog_id) : old_mute_until) != 0;
bool is_muted = (new_use_default ? get_scope_mute_until(d->dialog_id) : new_mute_until) != 0;
auto scope = get_dialog_notification_setting_scope(d->dialog_id);
auto scope_mute_until = td_->notification_settings_manager_->get_scope_mute_until(scope);
bool was_muted = (old_use_default ? scope_mute_until : old_mute_until) != 0;
bool is_muted = (new_use_default ? scope_mute_until : new_mute_until) != 0;
if (was_muted != is_muted && need_unread_counter(d->order)) {
auto unread_count = d->server_unread_count + d->local_unread_count;
if (unread_count != 0 || d->is_marked_as_unread) {
@ -8029,100 +7945,72 @@ void MessagesManager::update_dialog_unmute_timeout(Dialog *d, bool &old_use_defa
}
}
void MessagesManager::schedule_scope_unmute(NotificationSettingsScope scope, int32 mute_until) {
auto now = G()->unix_time_cached();
if (mute_until >= now && mute_until < now + 366 * 86400) {
dialog_unmute_timeout_.set_timeout_in(static_cast<int64>(scope) + 1, mute_until - now + 1);
} else {
dialog_unmute_timeout_.cancel_timeout(static_cast<int64>(scope) + 1);
}
}
void MessagesManager::update_scope_unmute_timeout(NotificationSettingsScope scope, int32 &old_mute_until,
int32 new_mute_until) {
if (td_->auth_manager_->is_bot()) {
// just in case
return;
}
LOG(INFO) << "Update " << scope << " unmute timeout from " << old_mute_until << " to " << new_mute_until;
if (old_mute_until == new_mute_until) {
return;
}
CHECK(old_mute_until >= 0);
schedule_scope_unmute(scope, new_mute_until);
auto was_muted = old_mute_until != 0;
auto is_muted = new_mute_until != 0;
if (was_muted != is_muted) {
if (G()->parameters().use_message_db) {
std::unordered_map<DialogListId, int32, DialogListIdHash> delta;
std::unordered_map<DialogListId, int32, DialogListIdHash> total_count;
std::unordered_map<DialogListId, int32, DialogListIdHash> marked_count;
std::unordered_set<DialogListId, DialogListIdHash> dialog_list_ids;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (need_unread_counter(d->order) && d->notification_settings.use_default_mute_until &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
int32 unread_count = d->server_unread_count + d->local_unread_count;
if (unread_count != 0) {
for (auto dialog_list_id : get_dialog_list_ids(d)) {
delta[dialog_list_id] += unread_count;
total_count[dialog_list_id]++;
dialog_list_ids.insert(dialog_list_id);
}
} else if (d->is_marked_as_unread) {
for (auto dialog_list_id : get_dialog_list_ids(d)) {
total_count[dialog_list_id]++;
marked_count[dialog_list_id]++;
dialog_list_ids.insert(dialog_list_id);
}
void MessagesManager::on_update_notification_scope_is_muted(NotificationSettingsScope scope, bool is_muted) {
if (G()->parameters().use_message_db) {
std::unordered_map<DialogListId, int32, DialogListIdHash> delta;
std::unordered_map<DialogListId, int32, DialogListIdHash> total_count;
std::unordered_map<DialogListId, int32, DialogListIdHash> marked_count;
std::unordered_set<DialogListId, DialogListIdHash> dialog_list_ids;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (need_unread_counter(d->order) && d->notification_settings.use_default_mute_until &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
int32 unread_count = d->server_unread_count + d->local_unread_count;
if (unread_count != 0) {
for (auto dialog_list_id : get_dialog_list_ids(d)) {
delta[dialog_list_id] += unread_count;
total_count[dialog_list_id]++;
dialog_list_ids.insert(dialog_list_id);
}
} else if (d->is_marked_as_unread) {
for (auto dialog_list_id : get_dialog_list_ids(d)) {
total_count[dialog_list_id]++;
marked_count[dialog_list_id]++;
dialog_list_ids.insert(dialog_list_id);
}
}
}
for (auto dialog_list_id : dialog_list_ids) {
auto *list = get_dialog_list(dialog_list_id);
CHECK(list != nullptr);
if (delta[dialog_list_id] != 0 && list->is_message_unread_count_inited_) {
if (was_muted) {
list->unread_message_muted_count_ -= delta[dialog_list_id];
} else {
list->unread_message_muted_count_ += delta[dialog_list_id];
}
send_update_unread_message_count(*list, DialogId(), true, "update_scope_unmute_timeout");
}
for (auto dialog_list_id : dialog_list_ids) {
auto *list = get_dialog_list(dialog_list_id);
CHECK(list != nullptr);
if (delta[dialog_list_id] != 0 && list->is_message_unread_count_inited_) {
if (is_muted) {
list->unread_message_muted_count_ += delta[dialog_list_id];
} else {
list->unread_message_muted_count_ -= delta[dialog_list_id];
}
if (total_count[dialog_list_id] != 0 && list->is_dialog_unread_count_inited_) {
if (was_muted) {
list->unread_dialog_muted_count_ -= total_count[dialog_list_id];
list->unread_dialog_muted_marked_count_ -= marked_count[dialog_list_id];
} else {
list->unread_dialog_muted_count_ += total_count[dialog_list_id];
list->unread_dialog_muted_marked_count_ += marked_count[dialog_list_id];
}
send_update_unread_chat_count(*list, DialogId(), true, "update_scope_unmute_timeout");
send_update_unread_message_count(*list, DialogId(), true, "on_update_notification_scope_is_muted");
}
if (total_count[dialog_list_id] != 0 && list->is_dialog_unread_count_inited_) {
if (is_muted) {
list->unread_dialog_muted_count_ += total_count[dialog_list_id];
list->unread_dialog_muted_marked_count_ += marked_count[dialog_list_id];
} else {
list->unread_dialog_muted_count_ -= total_count[dialog_list_id];
list->unread_dialog_muted_marked_count_ -= marked_count[dialog_list_id];
}
send_update_unread_chat_count(*list, DialogId(), true, "on_update_notification_scope_is_muted");
}
}
}
old_mute_until = new_mute_until;
if (was_muted != is_muted && !dialog_filters_.empty()) {
if (!dialog_filters_.empty()) {
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->order != DEFAULT_ORDER && d->notification_settings.use_default_mute_until &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
update_dialog_lists(d, get_dialog_positions(d), true, false, "update_scope_unmute_timeout");
update_dialog_lists(d, get_dialog_positions(d), true, false, "on_update_notification_scope_is_muted");
}
}
}
if (!was_muted && is_muted) {
if (is_muted) {
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->order != DEFAULT_ORDER && d->notification_settings.use_default_mute_until &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
remove_all_dialog_notifications(d, false, "update_scope_unmute_timeout");
remove_all_dialog_notifications(d, false, "on_update_notification_scope_is_muted");
}
}
}
@ -8161,33 +8049,6 @@ void MessagesManager::on_dialog_unmute(DialogId dialog_id) {
on_dialog_updated(dialog_id, "on_dialog_unmute");
}
void MessagesManager::on_scope_unmute(NotificationSettingsScope scope) {
if (td_->auth_manager_->is_bot()) {
// just in case
return;
}
auto notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
if (notification_settings->mute_until == 0) {
return;
}
auto now = G()->unix_time();
if (notification_settings->mute_until > now) {
LOG(ERROR) << "Failed to unmute " << scope << " in " << now << ", will be unmuted in "
<< notification_settings->mute_until;
schedule_scope_unmute(scope, notification_settings->mute_until);
return;
}
LOG(INFO) << "Unmute " << scope;
update_scope_unmute_timeout(scope, notification_settings->mute_until, 0);
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
save_scope_notification_settings(scope, *notification_settings);
}
void MessagesManager::on_update_dialog_notify_settings(
DialogId dialog_id, tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings, const char *source) {
if (td_->auth_manager_->is_bot()) {
@ -8213,25 +8074,6 @@ void MessagesManager::on_update_dialog_notify_settings(
update_dialog_notification_settings(dialog_id, current_settings, notification_settings);
}
void MessagesManager::on_update_scope_notify_settings(
NotificationSettingsScope scope, tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings) {
if (td_->auth_manager_->is_bot()) {
return;
}
auto old_notification_settings = get_scope_notification_settings(scope);
CHECK(old_notification_settings != nullptr);
const ScopeNotificationSettings notification_settings = ::td::get_scope_notification_settings(
std::move(peer_notify_settings), old_notification_settings->disable_pinned_message_notifications,
old_notification_settings->disable_mention_notifications);
if (!notification_settings.is_synchronized) {
return;
}
update_scope_notification_settings(scope, old_notification_settings, notification_settings);
}
void MessagesManager::on_update_dialog_available_reactions(DialogId dialog_id, vector<string> &&available_reactions) {
if (td_->auth_manager_->is_bot()) {
return;
@ -9558,8 +9400,6 @@ void MessagesManager::after_get_difference() {
td_->create_handler<GetDialogUnreadMarksQuery>()->send();
}
load_notification_settings();
auto dialog_list_id = DialogListId(FolderId::archive());
auto *list = get_dialog_list(dialog_list_id);
CHECK(list != nullptr);
@ -13164,6 +13004,8 @@ void MessagesManager::init() {
}
is_inited_ = true;
td_->notification_settings_manager_->init();
always_wait_for_mailbox();
start_time_ = Time::now();
@ -13179,35 +13021,6 @@ void MessagesManager::init() {
}
authorization_date_ = G()->shared_config().get_option_integer("authorization_date");
if (was_authorized_user) {
vector<NotificationSettingsScope> scopes{NotificationSettingsScope::Private, NotificationSettingsScope::Group,
NotificationSettingsScope::Channel};
for (auto scope : scopes) {
auto notification_settings_string =
G()->td_db()->get_binlog_pmc()->get(get_notification_settings_scope_database_key(scope));
if (!notification_settings_string.empty()) {
auto current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
log_event_parse(*current_settings, notification_settings_string).ensure();
VLOG(notifications) << "Loaded notification settings in " << scope << ": " << *current_settings;
schedule_scope_unmute(scope, current_settings->mute_until);
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
}
}
if (!channels_notification_settings_.is_synchronized && is_authorized) {
channels_notification_settings_ = chats_notification_settings_;
channels_notification_settings_.disable_pinned_message_notifications = false;
channels_notification_settings_.disable_mention_notifications = false;
channels_notification_settings_.is_synchronized = false;
td_->notification_settings_manager_->send_get_scope_notification_settings_query(
NotificationSettingsScope::Channel, Promise<>());
}
}
G()->td_db()->get_binlog_pmc()->erase("nsfac");
if (was_authorized_user) {
auto dialog_filters = G()->td_db()->get_binlog_pmc()->get("dialog_filters");
if (!dialog_filters.empty()) {
@ -15104,6 +14917,34 @@ void MessagesManager::remove_dialog_pinned_message_notification(Dialog *d, const
set_dialog_pinned_message_notification(d, MessageId(), source);
}
void MessagesManager::remove_scope_pinned_message_notifications(NotificationSettingsScope scope) {
VLOG(notifications) << "Remove pinned message notifications in " << scope;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->notification_settings.use_default_disable_pinned_message_notifications &&
d->mention_notification_group.group_id.is_valid() && d->pinned_message_notification_message_id.is_valid() &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
remove_dialog_pinned_message_notification(d, "remove_scope_pinned_message_notifications");
}
}
}
void MessagesManager::on_update_scope_mention_notifications(NotificationSettingsScope scope,
bool disable_mention_notifications) {
VLOG(notifications) << "Remove mention notifications in " << scope;
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
if (d->notification_settings.use_default_disable_mention_notifications &&
get_dialog_notification_setting_scope(d->dialog_id) == scope) {
if (!disable_mention_notifications) {
update_dialog_mention_notification_count(d);
} else {
remove_dialog_mention_notifications(d);
}
}
}
}
void MessagesManager::remove_dialog_mention_notifications(Dialog *d) {
auto notification_group_id = d->mention_notification_group.group_id;
if (!notification_group_id.is_valid()) {
@ -20333,8 +20174,12 @@ bool MessagesManager::is_dialog_inited(const Dialog *d) {
int32 MessagesManager::get_dialog_mute_until(const Dialog *d) const {
CHECK(!td_->auth_manager_->is_bot());
CHECK(d != nullptr);
return d->notification_settings.use_default_mute_until ? get_scope_mute_until(d->dialog_id)
: d->notification_settings.mute_until;
if (d->notification_settings.use_default_mute_until) {
auto scope = get_dialog_notification_setting_scope(d->dialog_id);
return td_->notification_settings_manager_->get_scope_mute_until(scope);
} else {
return d->notification_settings.mute_until;
}
}
bool MessagesManager::is_dialog_muted(const Dialog *d) const {
@ -20346,7 +20191,7 @@ bool MessagesManager::is_dialog_pinned_message_notifications_disabled(const Dial
CHECK(d != nullptr);
if (d->notification_settings.use_default_disable_pinned_message_notifications) {
auto scope = get_dialog_notification_setting_scope(d->dialog_id);
return get_scope_notification_settings(scope)->disable_pinned_message_notifications;
return td_->notification_settings_manager_->get_scope_disable_pinned_message_notifications(scope);
}
return d->notification_settings.disable_pinned_message_notifications;
@ -20357,7 +20202,7 @@ bool MessagesManager::is_dialog_mention_notifications_disabled(const Dialog *d)
CHECK(d != nullptr);
if (d->notification_settings.use_default_disable_mention_notifications) {
auto scope = get_dialog_notification_setting_scope(d->dialog_id);
return get_scope_notification_settings(scope)->disable_mention_notifications;
return td_->notification_settings_manager_->get_scope_disable_mention_notifications(scope);
}
return d->notification_settings.disable_mention_notifications;
@ -21307,18 +21152,11 @@ td_api::object_ptr<td_api::chatFilter> MessagesManager::get_chat_filter_object(c
filter->include_bots, filter->include_groups, filter->include_channels);
}
td_api::object_ptr<td_api::updateScopeNotificationSettings>
MessagesManager::get_update_scope_notification_settings_object(NotificationSettingsScope scope) const {
auto notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
return td_api::make_object<td_api::updateScopeNotificationSettings>(
get_notification_settings_scope_object(scope), get_scope_notification_settings_object(notification_settings));
}
std::pair<bool, int32> MessagesManager::get_dialog_mute_until(DialogId dialog_id, const Dialog *d) const {
CHECK(!td_->auth_manager_->is_bot());
if (d == nullptr || !d->notification_settings.is_synchronized) {
return {false, get_scope_mute_until(dialog_id)};
auto scope = get_dialog_notification_setting_scope(dialog_id);
return {false, td_->notification_settings_manager_->get_scope_mute_until(scope)};
}
return {d->notification_settings.is_use_default_fixed, get_dialog_mute_until(d)};
@ -21340,23 +21178,6 @@ NotificationSettingsScope MessagesManager::get_dialog_notification_setting_scope
}
}
int32 MessagesManager::get_scope_mute_until(DialogId dialog_id) const {
switch (dialog_id.get_type()) {
case DialogType::User:
case DialogType::SecretChat:
return users_notification_settings_.mute_until;
case DialogType::Chat:
return chats_notification_settings_.mute_until;
case DialogType::Channel:
return is_broadcast_channel(dialog_id) ? channels_notification_settings_.mute_until
: chats_notification_settings_.mute_until;
case DialogType::None:
default:
UNREACHABLE();
return 0;
}
}
vector<DialogId> MessagesManager::get_dialog_notification_settings_exceptions(NotificationSettingsScope scope,
bool filter_scope, bool compare_sound,
bool force, Promise<Unit> &&promise) {
@ -21417,19 +21238,6 @@ vector<DialogId> MessagesManager::get_dialog_notification_settings_exceptions(No
return {};
}
const ScopeNotificationSettings *MessagesManager::get_scope_notification_settings(NotificationSettingsScope scope,
Promise<Unit> &&promise) {
const ScopeNotificationSettings *notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
if (!notification_settings->is_synchronized && !td_->auth_manager_->is_bot()) {
td_->notification_settings_manager_->send_get_scope_notification_settings_query(scope, std::move(promise));
return nullptr;
}
promise.set_value(Unit());
return notification_settings;
}
DialogNotificationSettings *MessagesManager::get_dialog_notification_settings(DialogId dialog_id, bool force) {
Dialog *d = get_dialog_force(dialog_id, "get_dialog_notification_settings");
if (d == nullptr) {
@ -21441,35 +21249,6 @@ DialogNotificationSettings *MessagesManager::get_dialog_notification_settings(Di
return &d->notification_settings;
}
ScopeNotificationSettings *MessagesManager::get_scope_notification_settings(NotificationSettingsScope scope) {
switch (scope) {
case NotificationSettingsScope::Private:
return &users_notification_settings_;
case NotificationSettingsScope::Group:
return &chats_notification_settings_;
case NotificationSettingsScope::Channel:
return &channels_notification_settings_;
default:
UNREACHABLE();
return nullptr;
}
}
const ScopeNotificationSettings *MessagesManager::get_scope_notification_settings(
NotificationSettingsScope scope) const {
switch (scope) {
case NotificationSettingsScope::Private:
return &users_notification_settings_;
case NotificationSettingsScope::Group:
return &chats_notification_settings_;
case NotificationSettingsScope::Channel:
return &channels_notification_settings_;
default:
UNREACHABLE();
return nullptr;
}
}
tl_object_ptr<telegram_api::InputNotifyPeer> MessagesManager::get_input_notify_peer(DialogId dialog_id) const {
if (get_dialog(dialog_id) == nullptr) {
return nullptr;
@ -21500,67 +21279,18 @@ Status MessagesManager::set_dialog_notification_settings(
return Status::OK();
}
Status MessagesManager::set_scope_notification_settings(
NotificationSettingsScope scope, tl_object_ptr<td_api::scopeNotificationSettings> &&notification_settings) {
CHECK(!td_->auth_manager_->is_bot());
TRY_RESULT(new_settings, ::td::get_scope_notification_settings(std::move(notification_settings)));
if (update_scope_notification_settings(scope, get_scope_notification_settings(scope), new_settings)) {
update_scope_notification_settings_on_server(scope, 0);
}
return Status::OK();
}
class MessagesManager::UpdateScopeNotificationSettingsOnServerLogEvent {
public:
NotificationSettingsScope scope_;
template <class StorerT>
void store(StorerT &storer) const {
td::store(scope_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(scope_, parser);
}
};
uint64 MessagesManager::save_update_scope_notification_settings_on_server_log_event(NotificationSettingsScope scope) {
UpdateScopeNotificationSettingsOnServerLogEvent log_event{scope};
return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer,
get_log_event_storer(log_event));
}
void MessagesManager::update_scope_notification_settings_on_server(NotificationSettingsScope scope,
uint64 log_event_id) {
CHECK(!td_->auth_manager_->is_bot());
if (log_event_id == 0) {
log_event_id = save_update_scope_notification_settings_on_server_log_event(scope);
}
LOG(INFO) << "Update " << scope << " notification settings on server with log_event " << log_event_id;
td_->notification_settings_manager_->update_scope_notify_settings(scope, *get_scope_notification_settings(scope),
get_erase_log_event_promise(log_event_id));
}
void MessagesManager::reset_all_notification_settings() {
CHECK(!td_->auth_manager_->is_bot());
DialogNotificationSettings new_dialog_settings;
ScopeNotificationSettings new_scope_settings;
new_dialog_settings.is_synchronized = true;
new_scope_settings.is_synchronized = true;
update_scope_notification_settings(NotificationSettingsScope::Private, &users_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Group, &chats_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Channel, &channels_notification_settings_,
new_scope_settings);
for (auto &dialog : dialogs_) {
Dialog *d = dialog.second.get();
update_dialog_notification_settings(d->dialog_id, &d->notification_settings, new_dialog_settings);
}
td_->notification_settings_manager_->reset_scope_notification_settings();
reset_all_notification_settings_on_server(0);
}
@ -36288,15 +36018,6 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
have_input_peer(dialog_id, AccessRights::Read) && !td_->auth_manager_->is_bot()) {
LOG(INFO) << "Reget notification settings of " << dialog_id;
if (dialog_type == DialogType::SecretChat) {
if (d->notification_settings.mute_until == 0 && users_notification_settings_.mute_until == 0) {
d->notification_settings.use_default_mute_until = true;
}
if (d->notification_settings.sound == "default" && users_notification_settings_.sound == "default") {
d->notification_settings.use_default_sound = true;
}
if (d->notification_settings.show_preview && users_notification_settings_.show_preview) {
d->notification_settings.use_default_show_preview = true;
}
d->notification_settings.is_use_default_fixed = true;
on_dialog_updated(dialog_id, "reget notification settings");
} else {
@ -37630,24 +37351,6 @@ const MessagesManager::DialogFolder *MessagesManager::get_dialog_folder(FolderId
return &it->second;
}
void MessagesManager::load_notification_settings() {
if (td_->auth_manager_->is_bot()) {
return;
}
if (!users_notification_settings_.is_synchronized) {
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Private,
Promise<>());
}
if (!chats_notification_settings_.is_synchronized) {
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Group,
Promise<>());
}
if (!channels_notification_settings_.is_synchronized) {
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel,
Promise<>());
}
}
string MessagesManager::get_channel_pts_key(DialogId dialog_id) {
CHECK(dialog_id.get_type() == DialogType::Channel);
auto channel_id = dialog_id.get_channel_id();
@ -39375,13 +39078,6 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
update_dialog_notification_settings_on_server(dialog_id, true);
break;
}
case LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer: {
UpdateScopeNotificationSettingsOnServerLogEvent log_event;
log_event_parse(log_event, event.data_).ensure();
update_scope_notification_settings_on_server(log_event.scope_, event.id_);
break;
}
case LogEvent::HandlerType::ResetAllNotificationSettingsOnServer: {
ResetAllNotificationSettingsOnServerLogEvent log_event;
log_event_parse(log_event, event.data_).ensure();
@ -39895,16 +39591,6 @@ void MessagesManager::get_current_state(vector<td_api::object_ptr<td_api::Update
}
}
}
vector<NotificationSettingsScope> scopes{NotificationSettingsScope::Private, NotificationSettingsScope::Group,
NotificationSettingsScope::Channel};
for (auto scope : scopes) {
auto current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
if (current_settings->is_synchronized) {
updates.push_back(get_update_scope_notification_settings_object(scope));
}
}
}
vector<td_api::object_ptr<td_api::Update>> last_message_updates;

View File

@ -704,23 +704,13 @@ class MessagesManager final : public Actor {
void click_animated_emoji_message(FullMessageId full_message_id,
Promise<td_api::object_ptr<td_api::sticker>> &&promise);
td_api::object_ptr<td_api::updateScopeNotificationSettings> get_update_scope_notification_settings_object(
NotificationSettingsScope scope) const;
vector<DialogId> get_dialog_notification_settings_exceptions(NotificationSettingsScope scope, bool filter_scope,
bool compare_sound, bool force, Promise<Unit> &&promise);
const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope,
Promise<Unit> &&promise);
Status set_dialog_notification_settings(DialogId dialog_id,
tl_object_ptr<td_api::chatNotificationSettings> &&notification_settings)
TD_WARN_UNUSED_RESULT;
Status set_scope_notification_settings(NotificationSettingsScope scope,
tl_object_ptr<td_api::scopeNotificationSettings> &&notification_settings)
TD_WARN_UNUSED_RESULT;
void reset_all_notification_settings();
tl_object_ptr<td_api::chat> get_chat_object(DialogId dialog_id) const;
@ -858,13 +848,12 @@ class MessagesManager final : public Actor {
tl_object_ptr<telegram_api::InputNotifyPeer> get_input_notify_peer(DialogId dialog_id) const;
void on_update_notification_scope_is_muted(NotificationSettingsScope scope, bool is_muted);
void on_update_dialog_notify_settings(DialogId dialog_id,
tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings,
const char *source);
void on_update_scope_notify_settings(NotificationSettingsScope scope,
tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings);
void on_update_dialog_available_reactions(DialogId dialog_id, vector<string> &&available_reactions);
void hide_dialog_action_bar(DialogId dialog_id);
@ -966,6 +955,10 @@ class MessagesManager final : public Actor {
void remove_message_notifications(DialogId dialog_id, NotificationGroupId group_id,
NotificationId max_notification_id, MessageId max_message_id);
void remove_scope_pinned_message_notifications(NotificationSettingsScope scope);
void on_update_scope_mention_notifications(NotificationSettingsScope scope, bool disable_mention_notifications);
void upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, double main_frame_timestamp,
bool is_reupload, Promise<Unit> &&promise, vector<int> bad_parts = {});
@ -1742,7 +1735,6 @@ class MessagesManager final : public Actor {
class ToggleDialogReportSpamStateOnServerLogEvent;
class UnpinAllDialogMessagesOnServerLogEvent;
class UpdateDialogNotificationSettingsOnServerLogEvent;
class UpdateScopeNotificationSettingsOnServerLogEvent;
class DialogFiltersLogEvent;
@ -2613,30 +2605,16 @@ class MessagesManager final : public Actor {
bool set_dialog_last_notification(DialogId dialog_id, NotificationGroupInfo &group_info, int32 last_notification_date,
NotificationId last_notification_id, const char *source);
static string get_notification_settings_scope_database_key(NotificationSettingsScope scope);
static void save_scope_notification_settings(NotificationSettingsScope scope,
const ScopeNotificationSettings &new_settings);
bool update_dialog_notification_settings(DialogId dialog_id, DialogNotificationSettings *current_settings,
const DialogNotificationSettings &new_settings);
bool update_scope_notification_settings(NotificationSettingsScope scope, ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings);
void schedule_dialog_unmute(DialogId dialog_id, bool use_default, int32 mute_until);
void update_dialog_unmute_timeout(Dialog *d, bool &old_use_default, int32 &old_mute_until, bool new_use_default,
int32 new_mute_until);
void schedule_scope_unmute(NotificationSettingsScope scope, int32 mute_until);
void update_scope_unmute_timeout(NotificationSettingsScope scope, int32 &old_mute_until, int32 new_mute_until);
void on_dialog_unmute(DialogId dialog_id);
void on_scope_unmute(NotificationSettingsScope scope);
bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message);
vector<string> get_message_available_reactions(const Dialog *d, const Message *m);
@ -2863,14 +2841,8 @@ class MessagesManager final : public Actor {
NotificationSettingsScope get_dialog_notification_setting_scope(DialogId dialog_id) const;
int32 get_scope_mute_until(DialogId dialog_id) const;
DialogNotificationSettings *get_dialog_notification_settings(DialogId dialog_id, bool force);
ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope);
const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope) const;
vector<FileId> get_message_file_ids(const Message *m) const;
void cancel_upload_message_content_files(const MessageContent *content);
@ -3036,8 +3008,6 @@ class MessagesManager final : public Actor {
void on_updated_dialog_notification_settings(DialogId dialog_id, uint64 generation);
void update_scope_notification_settings_on_server(NotificationSettingsScope scope, uint64 log_event_id);
void reset_all_notification_settings_on_server(uint64 log_event_id);
void toggle_dialog_report_spam_state_on_server(DialogId dialog_id, bool is_spam_dialog, uint64 log_event_id,
@ -3071,8 +3041,6 @@ class MessagesManager final : public Actor {
void update_list_last_dialog_date(DialogList &list);
void load_notification_settings();
static string get_channel_pts_key(DialogId dialog_id);
int32 load_channel_pts(DialogId dialog_id) const;
@ -3261,8 +3229,6 @@ class MessagesManager final : public Actor {
static uint64 save_read_message_contents_on_server_log_event(DialogId dialog_id,
const vector<MessageId> &message_ids);
static uint64 save_update_scope_notification_settings_on_server_log_event(NotificationSettingsScope scope);
static uint64 save_reset_all_notification_settings_on_server_log_event();
static uint64 save_reget_dialog_log_event(DialogId dialog_id);
@ -3519,10 +3485,6 @@ class MessagesManager final : public Actor {
FlatHashMap<DialogId, std::vector<ActiveDialogAction>, DialogIdHash> active_dialog_actions_;
ScopeNotificationSettings users_notification_settings_;
ScopeNotificationSettings chats_notification_settings_;
ScopeNotificationSettings channels_notification_settings_;
FlatHashMap<NotificationGroupId, DialogId, NotificationGroupIdHash> notification_group_id_to_dialog_id_;
uint64 current_message_edit_generation_ = 0;

View File

@ -10,11 +10,19 @@
#include "td/telegram/AuthManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/logevent/LogEventHelper.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationSettings.hpp"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UpdatesManager.h"
#include "td/db/binlog/BinlogEvent.h"
#include "td/db/binlog/BinlogHelper.h"
#include "td/utils/algorithm.h"
#include "td/utils/buffer.h"
#include "td/utils/logging.h"
@ -135,7 +143,7 @@ class GetScopeNotifySettingsQuery final : public Td::ResultHandler {
}
auto ptr = result_ptr.move_as_ok();
td_->messages_manager_->on_update_scope_notify_settings(scope_, std::move(ptr));
td_->notification_settings_manager_->on_update_scope_notify_settings(scope_, std::move(ptr));
promise_.set_value(Unit());
}
@ -291,6 +299,8 @@ class ResetNotifySettingsQuery final : public Td::ResultHandler {
NotificationSettingsManager::NotificationSettingsManager(Td *td, ActorShared<> parent)
: td_(td), parent_(std::move(parent)) {
scope_unmute_timeout_.set_callback(on_scope_unmute_timeout_callback);
scope_unmute_timeout_.set_callback_data(static_cast<void *>(this));
}
NotificationSettingsManager::~NotificationSettingsManager() = default;
@ -299,6 +309,265 @@ void NotificationSettingsManager::tear_down() {
parent_.reset();
}
void NotificationSettingsManager::start_up() {
init();
}
void NotificationSettingsManager::init() {
if (is_inited_) {
return;
}
is_inited_ = true;
bool is_authorized = td_->auth_manager_->is_authorized();
bool was_authorized_user = td_->auth_manager_->was_authorized() && !td_->auth_manager_->is_bot();
if (was_authorized_user) {
for (auto scope :
{NotificationSettingsScope::Private, NotificationSettingsScope::Group, NotificationSettingsScope::Channel}) {
auto notification_settings_string =
G()->td_db()->get_binlog_pmc()->get(get_notification_settings_scope_database_key(scope));
if (!notification_settings_string.empty()) {
auto current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
log_event_parse(*current_settings, notification_settings_string).ensure();
VLOG(notifications) << "Loaded notification settings in " << scope << ": " << *current_settings;
schedule_scope_unmute(scope, current_settings->mute_until);
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
}
}
if (!channels_notification_settings_.is_synchronized && is_authorized) {
channels_notification_settings_ = chats_notification_settings_;
channels_notification_settings_.disable_pinned_message_notifications = false;
channels_notification_settings_.disable_mention_notifications = false;
channels_notification_settings_.is_synchronized = false;
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
}
}
G()->td_db()->get_binlog_pmc()->erase("nsfac");
}
void NotificationSettingsManager::on_scope_unmute_timeout_callback(void *notification_settings_manager_ptr,
int64 scope_int) {
if (G()->close_flag()) {
return;
}
CHECK(1 <= scope_int && scope_int <= 3);
auto notification_settings_manager = static_cast<NotificationSettingsManager *>(notification_settings_manager_ptr);
send_closure_later(notification_settings_manager->actor_id(notification_settings_manager),
&NotificationSettingsManager::on_scope_unmute,
static_cast<NotificationSettingsScope>(scope_int - 1));
}
int32 NotificationSettingsManager::get_scope_mute_until(NotificationSettingsScope scope) const {
return get_scope_notification_settings(scope)->mute_until;
}
bool NotificationSettingsManager::get_scope_disable_pinned_message_notifications(
NotificationSettingsScope scope) const {
return get_scope_notification_settings(scope)->disable_pinned_message_notifications;
}
bool NotificationSettingsManager::get_scope_disable_mention_notifications(NotificationSettingsScope scope) const {
return get_scope_notification_settings(scope)->disable_mention_notifications;
}
ScopeNotificationSettings *NotificationSettingsManager::get_scope_notification_settings(
NotificationSettingsScope scope) {
switch (scope) {
case NotificationSettingsScope::Private:
return &users_notification_settings_;
case NotificationSettingsScope::Group:
return &chats_notification_settings_;
case NotificationSettingsScope::Channel:
return &channels_notification_settings_;
default:
UNREACHABLE();
return nullptr;
}
}
const ScopeNotificationSettings *NotificationSettingsManager::get_scope_notification_settings(
NotificationSettingsScope scope) const {
switch (scope) {
case NotificationSettingsScope::Private:
return &users_notification_settings_;
case NotificationSettingsScope::Group:
return &chats_notification_settings_;
case NotificationSettingsScope::Channel:
return &channels_notification_settings_;
default:
UNREACHABLE();
return nullptr;
}
}
td_api::object_ptr<td_api::updateScopeNotificationSettings>
NotificationSettingsManager::get_update_scope_notification_settings_object(NotificationSettingsScope scope) const {
auto notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
return td_api::make_object<td_api::updateScopeNotificationSettings>(
get_notification_settings_scope_object(scope), get_scope_notification_settings_object(notification_settings));
}
void NotificationSettingsManager::on_scope_unmute(NotificationSettingsScope scope) {
if (td_->auth_manager_->is_bot()) {
// just in case
return;
}
auto notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
if (notification_settings->mute_until == 0) {
return;
}
auto now = G()->unix_time();
if (notification_settings->mute_until > now) {
LOG(ERROR) << "Failed to unmute " << scope << " in " << now << ", will be unmuted in "
<< notification_settings->mute_until;
schedule_scope_unmute(scope, notification_settings->mute_until);
return;
}
LOG(INFO) << "Unmute " << scope;
update_scope_unmute_timeout(scope, notification_settings->mute_until, 0);
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
save_scope_notification_settings(scope, *notification_settings);
}
string NotificationSettingsManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) {
switch (scope) {
case NotificationSettingsScope::Private:
return "nsfpc";
case NotificationSettingsScope::Group:
return "nsfgc";
case NotificationSettingsScope::Channel:
return "nsfcc";
default:
UNREACHABLE();
return "";
}
}
void NotificationSettingsManager::save_scope_notification_settings(NotificationSettingsScope scope,
const ScopeNotificationSettings &new_settings) {
string key = get_notification_settings_scope_database_key(scope);
G()->td_db()->get_binlog_pmc()->set(key, log_event_store(new_settings).as_slice().str());
}
void NotificationSettingsManager::on_update_scope_notify_settings(
NotificationSettingsScope scope, tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings) {
if (td_->auth_manager_->is_bot()) {
return;
}
auto old_notification_settings = get_scope_notification_settings(scope);
CHECK(old_notification_settings != nullptr);
const ScopeNotificationSettings notification_settings = ::td::get_scope_notification_settings(
std::move(peer_notify_settings), old_notification_settings->disable_pinned_message_notifications,
old_notification_settings->disable_mention_notifications);
if (!notification_settings.is_synchronized) {
return;
}
update_scope_notification_settings(scope, old_notification_settings, notification_settings);
}
bool NotificationSettingsManager::update_scope_notification_settings(NotificationSettingsScope scope,
ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings) {
if (td_->auth_manager_->is_bot()) {
// just in case
return false;
}
bool need_update_server = current_settings->mute_until != new_settings.mute_until ||
current_settings->sound != new_settings.sound ||
current_settings->show_preview != new_settings.show_preview;
bool need_update_local =
current_settings->disable_pinned_message_notifications != new_settings.disable_pinned_message_notifications ||
current_settings->disable_mention_notifications != new_settings.disable_mention_notifications;
bool was_inited = current_settings->is_synchronized;
bool is_inited = new_settings.is_synchronized;
if (was_inited && !is_inited) {
return false; // just in case
}
bool is_changed = need_update_server || need_update_local || was_inited != is_inited;
if (is_changed) {
save_scope_notification_settings(scope, new_settings);
VLOG(notifications) << "Update notification settings in " << scope << " from " << *current_settings << " to "
<< new_settings;
update_scope_unmute_timeout(scope, current_settings->mute_until, new_settings.mute_until);
if (!current_settings->disable_pinned_message_notifications && new_settings.disable_pinned_message_notifications) {
td_->messages_manager_->remove_scope_pinned_message_notifications(scope);
}
if (current_settings->disable_mention_notifications != new_settings.disable_mention_notifications) {
td_->messages_manager_->on_update_scope_mention_notifications(scope, new_settings.disable_mention_notifications);
}
*current_settings = new_settings;
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
}
return need_update_server;
}
void NotificationSettingsManager::schedule_scope_unmute(NotificationSettingsScope scope, int32 mute_until) {
auto now = G()->unix_time_cached();
if (mute_until >= now && mute_until < now + 366 * 86400) {
scope_unmute_timeout_.set_timeout_in(static_cast<int64>(scope) + 1, mute_until - now + 1);
} else {
scope_unmute_timeout_.cancel_timeout(static_cast<int64>(scope) + 1);
}
}
void NotificationSettingsManager::update_scope_unmute_timeout(NotificationSettingsScope scope, int32 &old_mute_until,
int32 new_mute_until) {
if (td_->auth_manager_->is_bot()) {
// just in case
return;
}
LOG(INFO) << "Update " << scope << " unmute timeout from " << old_mute_until << " to " << new_mute_until;
if (old_mute_until == new_mute_until) {
return;
}
CHECK(old_mute_until >= 0);
schedule_scope_unmute(scope, new_mute_until);
auto was_muted = old_mute_until != 0;
auto is_muted = new_mute_until != 0;
old_mute_until = new_mute_until;
if (was_muted != is_muted) {
td_->messages_manager_->on_update_notification_scope_is_muted(scope, is_muted);
}
}
void NotificationSettingsManager::reset_scope_notification_settings() {
CHECK(!td_->auth_manager_->is_bot());
ScopeNotificationSettings new_scope_settings;
new_scope_settings.is_synchronized = true;
update_scope_notification_settings(NotificationSettingsScope::Private, &users_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Group, &chats_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Channel, &channels_notification_settings_,
new_scope_settings);
}
void NotificationSettingsManager::send_get_dialog_notification_settings_query(DialogId dialog_id,
Promise<Unit> &&promise) {
if (td_->auth_manager_->is_bot() || dialog_id.get_type() == DialogType::SecretChat) {
@ -320,6 +589,19 @@ void NotificationSettingsManager::send_get_dialog_notification_settings_query(Di
td_->create_handler<GetDialogNotifySettingsQuery>()->send(dialog_id);
}
const ScopeNotificationSettings *NotificationSettingsManager::get_scope_notification_settings(
NotificationSettingsScope scope, Promise<Unit> &&promise) {
const ScopeNotificationSettings *notification_settings = get_scope_notification_settings(scope);
CHECK(notification_settings != nullptr);
if (!notification_settings->is_synchronized && !td_->auth_manager_->is_bot()) {
send_get_scope_notification_settings_query(scope, std::move(promise));
return nullptr;
}
promise.set_value(Unit());
return notification_settings;
}
void NotificationSettingsManager::send_get_scope_notification_settings_query(NotificationSettingsScope scope,
Promise<Unit> &&promise) {
if (td_->auth_manager_->is_bot()) {
@ -354,10 +636,48 @@ void NotificationSettingsManager::update_dialog_notify_settings(DialogId dialog_
td_->create_handler<UpdateDialogNotifySettingsQuery>(std::move(promise))->send(dialog_id, new_settings);
}
void NotificationSettingsManager::update_scope_notify_settings(NotificationSettingsScope scope,
const ScopeNotificationSettings &new_settings,
Promise<Unit> &&promise) {
td_->create_handler<UpdateScopeNotifySettingsQuery>(std::move(promise))->send(scope, new_settings);
Status NotificationSettingsManager::set_scope_notification_settings(
NotificationSettingsScope scope, td_api::object_ptr<td_api::scopeNotificationSettings> &&notification_settings) {
CHECK(!td_->auth_manager_->is_bot());
TRY_RESULT(new_settings, ::td::get_scope_notification_settings(std::move(notification_settings)));
if (update_scope_notification_settings(scope, get_scope_notification_settings(scope), new_settings)) {
update_scope_notification_settings_on_server(scope, 0);
}
return Status::OK();
}
class NotificationSettingsManager::UpdateScopeNotificationSettingsOnServerLogEvent {
public:
NotificationSettingsScope scope_;
template <class StorerT>
void store(StorerT &storer) const {
td::store(scope_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(scope_, parser);
}
};
uint64 NotificationSettingsManager::save_update_scope_notification_settings_on_server_log_event(
NotificationSettingsScope scope) {
UpdateScopeNotificationSettingsOnServerLogEvent log_event{scope};
return binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer,
get_log_event_storer(log_event));
}
void NotificationSettingsManager::update_scope_notification_settings_on_server(NotificationSettingsScope scope,
uint64 log_event_id) {
CHECK(!td_->auth_manager_->is_bot());
if (log_event_id == 0) {
log_event_id = save_update_scope_notification_settings_on_server_log_event(scope);
}
LOG(INFO) << "Update " << scope << " notification settings on server with log_event " << log_event_id;
td_->create_handler<UpdateScopeNotifySettingsQuery>(get_erase_log_event_promise(log_event_id))
->send(scope, *get_scope_notification_settings(scope));
}
void NotificationSettingsManager::reset_notify_settings(Promise<Unit> &&promise) {
@ -369,4 +689,55 @@ void NotificationSettingsManager::get_notify_settings_exceptions(NotificationSet
td_->create_handler<GetNotifySettingsExceptionsQuery>(std::move(promise))->send(scope, filter_scope, compare_sound);
}
void NotificationSettingsManager::after_get_difference() {
if (td_->auth_manager_->is_bot()) {
return;
}
if (!users_notification_settings_.is_synchronized) {
send_get_scope_notification_settings_query(NotificationSettingsScope::Private, Promise<>());
}
if (!chats_notification_settings_.is_synchronized) {
send_get_scope_notification_settings_query(NotificationSettingsScope::Group, Promise<>());
}
if (!channels_notification_settings_.is_synchronized) {
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
}
}
void NotificationSettingsManager::on_binlog_events(vector<BinlogEvent> &&events) {
if (G()->close_flag()) {
return;
}
for (auto &event : events) {
CHECK(event.id_ != 0);
switch (event.type_) {
case LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer: {
UpdateScopeNotificationSettingsOnServerLogEvent log_event;
log_event_parse(log_event, event.data_).ensure();
update_scope_notification_settings_on_server(log_event.scope_, event.id_);
break;
}
default:
LOG(FATAL) << "Unsupported log event type " << event.type_;
}
}
}
void NotificationSettingsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
if (td_->auth_manager_->is_bot()) {
return;
}
for (auto scope :
{NotificationSettingsScope::Private, NotificationSettingsScope::Group, NotificationSettingsScope::Channel}) {
auto current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
if (current_settings->is_synchronized) {
updates.push_back(get_update_scope_notification_settings_object(scope));
}
}
}
} // namespace td

View File

@ -8,9 +8,12 @@
#include "td/telegram/DialogId.h"
#include "td/telegram/NotificationSettings.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/Timeout.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
@ -18,6 +21,8 @@
namespace td {
struct BinlogEvent;
class Td;
class NotificationSettingsManager final : public Actor {
@ -29,8 +34,19 @@ class NotificationSettingsManager final : public Actor {
NotificationSettingsManager &operator=(NotificationSettingsManager &&) = delete;
~NotificationSettingsManager() final;
int32 get_scope_mute_until(NotificationSettingsScope scope) const;
bool get_scope_disable_pinned_message_notifications(NotificationSettingsScope scope) const;
bool get_scope_disable_mention_notifications(NotificationSettingsScope scope) const;
void on_update_scope_notify_settings(NotificationSettingsScope scope,
tl_object_ptr<telegram_api::peerNotifySettings> &&peer_notify_settings);
void send_get_dialog_notification_settings_query(DialogId dialog_id, Promise<Unit> &&promise);
const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope,
Promise<Unit> &&promise);
void send_get_scope_notification_settings_query(NotificationSettingsScope scope, Promise<Unit> &&promise);
void on_get_dialog_notification_settings_query_finished(DialogId dialog_id, Status &&status);
@ -38,20 +54,70 @@ class NotificationSettingsManager final : public Actor {
void update_dialog_notify_settings(DialogId dialog_id, const DialogNotificationSettings &new_settings,
Promise<Unit> &&promise);
void update_scope_notify_settings(NotificationSettingsScope scope, const ScopeNotificationSettings &new_settings,
Promise<Unit> &&promise);
Status set_scope_notification_settings(NotificationSettingsScope scope,
td_api::object_ptr<td_api::scopeNotificationSettings> &&notification_settings)
TD_WARN_UNUSED_RESULT;
void reset_scope_notification_settings();
void reset_notify_settings(Promise<Unit> &&promise);
void get_notify_settings_exceptions(NotificationSettingsScope scope, bool filter_scope, bool compare_sound,
Promise<Unit> &&promise);
void init();
void after_get_difference();
void on_binlog_events(vector<BinlogEvent> &&events);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
class UpdateScopeNotificationSettingsOnServerLogEvent;
void start_up() final;
void tear_down() final;
static void on_scope_unmute_timeout_callback(void *notification_settings_manager_ptr, int64 scope_int);
ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope);
const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope) const;
td_api::object_ptr<td_api::updateScopeNotificationSettings> get_update_scope_notification_settings_object(
NotificationSettingsScope scope) const;
void on_scope_unmute(NotificationSettingsScope scope);
static string get_notification_settings_scope_database_key(NotificationSettingsScope scope);
static void save_scope_notification_settings(NotificationSettingsScope scope,
const ScopeNotificationSettings &new_settings);
bool update_scope_notification_settings(NotificationSettingsScope scope, ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings);
static uint64 save_update_scope_notification_settings_on_server_log_event(NotificationSettingsScope scope);
void update_scope_notification_settings_on_server(NotificationSettingsScope scope, uint64 log_event_id);
void schedule_scope_unmute(NotificationSettingsScope scope, int32 mute_until);
void update_scope_unmute_timeout(NotificationSettingsScope scope, int32 &old_mute_until, int32 new_mute_until);
Td *td_;
ActorShared<> parent_;
bool is_inited_ = false;
ScopeNotificationSettings users_notification_settings_;
ScopeNotificationSettings chats_notification_settings_;
ScopeNotificationSettings channels_notification_settings_;
MultiTimeout scope_unmute_timeout_{"ScopeUnmuteTimeout"};
FlatHashMap<DialogId, vector<Promise<Unit>>, DialogIdHash> get_dialog_notification_settings_queries_;
};

View File

@ -2024,7 +2024,8 @@ class GetScopeNotificationSettingsRequest final : public RequestActor<> {
const ScopeNotificationSettings *notification_settings_ = nullptr;
void do_run(Promise<Unit> &&promise) final {
notification_settings_ = td_->messages_manager_->get_scope_notification_settings(scope_, std::move(promise));
notification_settings_ =
td_->notification_settings_manager_->get_scope_notification_settings(scope_, std::move(promise));
}
void do_send_result() final {
@ -3782,6 +3783,9 @@ Status Td::init(DbKey key) {
send_closure_later(notification_manager_actor_, &NotificationManager::on_binlog_events,
std::move(events.to_notification_manager));
send_closure_later(notification_settings_manager_actor_, &NotificationSettingsManager::on_binlog_events,
std::move(events.to_notification_settings_manager));
send_closure(secret_chats_manager_, &SecretChatsManager::binlog_replay_finish);
VLOG(td_init) << "Ping datacenter";
@ -4440,6 +4444,8 @@ void Td::on_request(uint64 id, const td_api::getCurrentState &request) {
stickers_manager_->get_current_state(updates);
notification_settings_manager_->get_current_state(updates);
messages_manager_->get_current_state(updates);
notification_manager_->get_current_state(updates);
@ -7199,7 +7205,7 @@ void Td::on_request(uint64 id, td_api::setScopeNotificationSettings &request) {
if (request.scope_ == nullptr) {
return send_error_raw(id, 400, "Scope must be non-empty");
}
answer_ok_query(id, messages_manager_->set_scope_notification_settings(
answer_ok_query(id, notification_settings_manager_->set_scope_notification_settings(
get_notification_settings_scope(request.scope_), std::move(request.notification_settings_)));
}

View File

@ -105,7 +105,6 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue<Binlog> &binlog_p
case LogEvent::HandlerType::ReorderPinnedDialogsOnServer:
case LogEvent::HandlerType::SaveDialogDraftMessageOnServer:
case LogEvent::HandlerType::UpdateDialogNotificationSettingsOnServer:
case LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer:
case LogEvent::HandlerType::ResetAllNotificationSettingsOnServer:
case LogEvent::HandlerType::ToggleDialogReportSpamStateOnServer:
case LogEvent::HandlerType::RegetDialog:
@ -123,6 +122,9 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue<Binlog> &binlog_p
case LogEvent::HandlerType::ReadAllDialogReactionsOnServer:
events.to_messages_manager.push_back(event.clone());
break;
case LogEvent::HandlerType::UpdateScopeNotificationSettingsOnServer:
events.to_notification_settings_manager.push_back(event.clone());
break;
case LogEvent::HandlerType::AddMessagePushNotification:
case LogEvent::HandlerType::EditMessagePushNotification:
events.to_notification_manager.push_back(event.clone());

View File

@ -58,6 +58,7 @@ class TdDb {
vector<BinlogEvent> to_poll_manager;
vector<BinlogEvent> to_messages_manager;
vector<BinlogEvent> to_notification_manager;
vector<BinlogEvent> to_notification_settings_manager;
};
static Result<unique_ptr<TdDb>> open(int32 scheduler_id, const TdParameters &parameters, DbKey key, Events &events);

View File

@ -33,6 +33,7 @@
#include "td/telegram/net/DcOptions.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/Payments.h"
#include "td/telegram/PollId.h"
#include "td/telegram/PollManager.h"
@ -1569,6 +1570,7 @@ void UpdatesManager::after_get_difference() {
td_->download_manager_->after_get_difference();
td_->inline_queries_manager_->after_get_difference();
td_->messages_manager_->after_get_difference();
td_->notification_settings_manager_->after_get_difference();
td_->stickers_manager_->after_get_difference();
send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference);
send_closure(G()->state_manager(), &StateManager::on_synchronized, true);
@ -2668,16 +2670,16 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateNotifySettings>
break;
}
case telegram_api::notifyUsers::ID:
td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Private,
std::move(update->notify_settings_));
td_->notification_settings_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Private,
std::move(update->notify_settings_));
break;
case telegram_api::notifyChats::ID:
td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Group,
std::move(update->notify_settings_));
td_->notification_settings_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Group,
std::move(update->notify_settings_));
break;
case telegram_api::notifyBroadcasts::ID:
td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Channel,
std::move(update->notify_settings_));
td_->notification_settings_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Channel,
std::move(update->notify_settings_));
break;
default:
UNREACHABLE();