diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 62ceed310..36fbc13eb 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -4476,6 +4476,9 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent) : td_(td), parent pending_unload_dialog_timeout_.set_callback(on_pending_unload_dialog_timeout_callback); pending_unload_dialog_timeout_.set_callback_data(static_cast(this)); + dialog_unmute_timeout_.set_callback(on_dialog_unmute_timeout_callback); + dialog_unmute_timeout_.set_callback_data(static_cast(this)); + sequence_dispatcher_ = create_actor("multi sequence dispatcher"); if (G()->parameters().use_message_db) { @@ -4565,6 +4568,16 @@ void MessagesManager::on_pending_unload_dialog_timeout_callback(void *messages_m messages_manager->unload_dialog(DialogId(dialog_id_int)); } +void MessagesManager::on_dialog_unmute_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) { + if (G()->close_flag()) { + return; + } + + auto messages_manager = static_cast(messages_manager_ptr); + send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_dialog_unmute, + DialogId(dialog_id_int)); +} + BufferSlice MessagesManager::get_dialog_database_value(const Dialog *d) { // can't use log_event_store, because it tries to parse stored Dialog LogEventStorerCalcLength storer_calc_length; @@ -5869,12 +5882,13 @@ bool MessagesManager::update_notification_settings(NotificationSettingsScope sco DialogId dialog_id(scope); CHECK(dialog_id.is_valid()); CHECK(have_dialog(dialog_id)) << "Wrong " << dialog_id << " in update_notification_settings"; + update_dialog_unmute_timeout(dialog_id, current_settings->mute_until, new_settings.mute_until); on_dialog_updated(dialog_id, "update_notification_settings"); } else { 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()); } - LOG(INFO) << "Update notification settings in " << scope; + LOG(INFO) << "Update notification settings in " << scope << " from " << *current_settings << " to " << new_settings; *current_settings = new_settings; if (need_update) { @@ -5887,6 +5901,45 @@ bool MessagesManager::update_notification_settings(NotificationSettingsScope sco return is_changed; } +void MessagesManager::update_dialog_unmute_timeout(DialogId dialog_id, int32 old_mute_until, int32 new_mute_until) { + if (old_mute_until == new_mute_until) { + return; + } + + auto now = G()->unix_time_cached(); + if (new_mute_until >= now && new_mute_until < now + 366 * 86400) { + dialog_unmute_timeout_.set_timeout_in(dialog_id.get(), new_mute_until - now + 1); + } else { + dialog_unmute_timeout_.cancel_timeout(dialog_id.get()); + } +} + +void MessagesManager::on_dialog_unmute(DialogId dialog_id) { + auto d = get_dialog(dialog_id); + CHECK(d != nullptr); + + if (d->notification_settings.mute_until == 0) { + return; + } + + auto now = G()->unix_time(); + if (d->notification_settings.mute_until > now) { + LOG(ERROR) << "Failed to unmute " << dialog_id << " in " << now << ", will be unmuted in " + << d->notification_settings.mute_until; + update_dialog_unmute_timeout(dialog_id, -1, d->notification_settings.mute_until); + return; + } + + LOG(INFO) << "Unmute " << dialog_id; + update_dialog_unmute_timeout(dialog_id, d->notification_settings.mute_until, 0); + d->notification_settings.mute_until = 0; + send_closure(G()->td(), &Td::send_update, + make_tl_object( + get_notification_settings_scope_object(NotificationSettingsScope(dialog_id.get())), + get_notification_settings_object(&d->notification_settings))); + on_dialog_updated(dialog_id, "on_dialog_unmute"); +} + void MessagesManager::on_update_notify_settings( NotificationSettingsScope scope, tl_object_ptr &&peer_notify_settings) { const NotificationSettings notification_settings = get_notification_settings(std::move(peer_notify_settings)); @@ -22484,6 +22537,8 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab CHECK(d != nullptr); auto dialog_id = d->dialog_id; + update_dialog_unmute_timeout(d->dialog_id, -1, d->notification_settings.mute_until); + auto pending_it = pending_add_dialog_last_database_message_dependent_dialogs_.find(dialog_id); if (pending_it != pending_add_dialog_last_database_message_dependent_dialogs_.end()) { auto pending_dialogs = std::move(pending_it->second); diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 59359766d..8db59e464 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -674,6 +674,12 @@ class NotificationSettings { } }; +inline StringBuilder &operator<<(StringBuilder &string_builder, NotificationSettings notification_settings) { + return string_builder << "[" << notification_settings.mute_until << ", " << notification_settings.sound << ", " + << notification_settings.show_preview << ", " << notification_settings.silent_send_message + << ", " << notification_settings.is_synchronized << "]"; +} + inline constexpr size_t search_messages_filter_size() { return static_cast(SearchMessagesFilter::Size) - 1; } @@ -2133,6 +2139,10 @@ class MessagesManager : public Actor { bool update_notification_settings(NotificationSettingsScope scope, NotificationSettings *current_settings, const NotificationSettings &new_settings); + void update_dialog_unmute_timeout(DialogId dialog_id, int32 old_mute_until, int32 new_mute_until); + + void on_dialog_unmute(DialogId dialog_id); + Dialog *get_dialog_by_message_id(MessageId message_id); MessageId get_message_id_by_random_id(Dialog *d, int64 random_id); @@ -2389,6 +2399,8 @@ class MessagesManager : public Actor { static void on_pending_unload_dialog_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int); + static void on_dialog_unmute_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int); + void load_secret_thumbnail(FileId thumbnail_file_id); static tl_object_ptr get_channel_admin_log_events_filter( @@ -2630,6 +2642,7 @@ class MessagesManager : public Actor { MultiTimeout pending_draft_message_timeout_; MultiTimeout pending_updated_dialog_timeout_; MultiTimeout pending_unload_dialog_timeout_; + MultiTimeout dialog_unmute_timeout_; Hints dialogs_hints_; // search dialogs by title and username