diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 85bdc33a..ee980d5f 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -15,6 +15,7 @@ #include "td/telegram/StateManager.h" #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" +#include "td/telegram/telegram_api.h" #include "td/mtproto/AuthKey.h" #include "td/mtproto/PacketInfo.h" @@ -39,6 +40,35 @@ namespace td { int VERBOSITY_NAME(notifications) = VERBOSITY_NAME(INFO); +class SetContactSignUpNotificationQuery : public Td::ResultHandler { + Promise promise_; + + public: + explicit SetContactSignUpNotificationQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(bool is_disabled) { + send_query(G()->net_query_creator().create( + create_storer(telegram_api::account_setContactSignUpNotification(is_disabled)))); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + if (!G()->close_flag()) { + LOG(ERROR) << "Receive error for set contact sign up notification: " << status; + } + promise_.set_error(std::move(status)); + } +}; + NotificationManager::NotificationManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { flush_pending_notifications_timeout_.set_callback(on_flush_pending_notifications_timeout_callback); flush_pending_notifications_timeout_.set_callback_data(static_cast(this)); @@ -114,7 +144,25 @@ ActiveNotificationsUpdate as_active_notifications_update(const td_api::updateAct } // namespace +string NotificationManager::get_is_contact_registered_notifications_synchronized_key() { + return "notifications_contact_registered_sync_state"; +} + void NotificationManager::start_up() { + disable_contact_registered_notifications_ = + G()->shared_config().get_option_boolean("disable_contact_registered_notifications"); + auto sync_state = G()->td_db()->get_binlog_pmc()->get(get_is_contact_registered_notifications_synchronized_key()); + if (sync_state.empty()) { + sync_state = "00"; + } + contact_registered_notifications_sync_state_ = static_cast(sync_state[0] - '0'); + VLOG(notifications) << "Loaded disable_contact_registered_notifications = " + << disable_contact_registered_notifications_ << " in state " << sync_state; + if (contact_registered_notifications_sync_state_ != SyncState::Completed || + static_cast(sync_state[1] - '0') != disable_contact_registered_notifications_) { + run_contact_registered_notifications_sync(); + } + if (is_disabled()) { return; } @@ -2057,6 +2105,62 @@ void NotificationManager::on_notification_default_delay_changed() { VLOG(notifications) << "Set notification_default_delay_ms to " << notification_default_delay_ms_; } +void NotificationManager::on_disable_contact_registered_notifications_changed() { + auto disable_contact_registered_notifications = + G()->shared_config().get_option_boolean("disable_contact_registered_notifications"); + + if (disable_contact_registered_notifications == disable_contact_registered_notifications_) { + return; + } + + disable_contact_registered_notifications_ = disable_contact_registered_notifications; + if (contact_registered_notifications_sync_state_ == SyncState::Completed) { + run_contact_registered_notifications_sync(); + } +} + +void NotificationManager::set_contact_registered_notifications_sync_state(SyncState new_state) { + contact_registered_notifications_sync_state_ = new_state; + string value; + value += static_cast(static_cast(new_state) + '0'); + value += static_cast(static_cast(disable_contact_registered_notifications_) + '0'); + G()->td_db()->get_binlog_pmc()->set(get_is_contact_registered_notifications_synchronized_key(), value); +} + +void NotificationManager::run_contact_registered_notifications_sync() { + auto is_disabled = disable_contact_registered_notifications_; + if (contact_registered_notifications_sync_state_ == SyncState::NotSynced && !is_disabled) { + set_contact_registered_notifications_sync_state(SyncState::Completed); + return; + } + if (contact_registered_notifications_sync_state_ != SyncState::Pending) { + set_contact_registered_notifications_sync_state(SyncState::Pending); + } + + VLOG(notifications) << "Send SetContactSignUpNotificationQuery with " << is_disabled; + auto promise = PromiseCreator::lambda([actor_id = actor_id(this), is_disabled](Result result) { + send_closure(actor_id, &NotificationManager::on_contact_registered_notifications_sync, is_disabled, + std::move(result)); + }); + td_->create_handler(std::move(promise))->send(is_disabled); +} + +void NotificationManager::on_contact_registered_notifications_sync(bool is_disabled, Result result) { + CHECK(contact_registered_notifications_sync_state_ == SyncState::Pending); + if (is_disabled != disable_contact_registered_notifications_) { + return run_contact_registered_notifications_sync(); + } + if (result.is_ok()) { + // everything is synchronized + set_contact_registered_notifications_sync_state(SyncState::Completed); + } else { + // let's resend the query forever + if (!G()->close_flag()) { + run_contact_registered_notifications_sync(); + } + } +} + void NotificationManager::process_push_notification(string payload, Promise &&promise) { if (is_disabled()) { promise.set_value(Unit()); diff --git a/td/telegram/NotificationManager.h b/td/telegram/NotificationManager.h index 06694c3d..188f0750 100644 --- a/td/telegram/NotificationManager.h +++ b/td/telegram/NotificationManager.h @@ -89,6 +89,8 @@ class NotificationManager : public Actor { void on_notification_default_delay_changed(); + void on_disable_contact_registered_notifications_changed(); + void process_push_notification(string payload, Promise &&promise); static Result get_push_receiver_id(string push); @@ -146,6 +148,8 @@ class NotificationManager : public Actor { vector pending_notifications; }; + enum class SyncState : int32 { NotSynced, Pending, Completed }; + using NotificationGroups = std::map; static void on_flush_pending_notifications_timeout_callback(void *notification_manager_ptr, int64 group_id_int); @@ -231,6 +235,14 @@ class NotificationManager : public Actor { void on_pending_notification_update_count_changed(int32 diff, int32 notification_group_id, const char *source); + static string get_is_contact_registered_notifications_synchronized_key(); + + void set_contact_registered_notifications_sync_state(SyncState new_state); + + void run_contact_registered_notifications_sync(); + + void on_contact_registered_notifications_sync(bool is_disabled, Result result); + NotificationId current_notification_id_; NotificationGroupId current_notification_group_id_; @@ -246,6 +258,9 @@ class NotificationManager : public Actor { NotificationGroupKey last_loaded_notification_group_key_; + SyncState contact_registered_notifications_sync_state_ = SyncState::NotSynced; + bool disable_contact_registered_notifications_ = false; + bool is_destroyed_ = false; bool running_get_difference_ = false; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 5fa2e316..8b527b86 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3483,6 +3483,9 @@ void Td::on_config_option_updated(const string &name) { send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer); } else if (name == "rating_e_decay") { return send_closure(top_dialog_manager_, &TopDialogManager::update_rating_e_decay); + } else if (name == "disable_contact_registered_notifications") { + send_closure(notification_manager_actor_, + &NotificationManager::on_disable_contact_registered_notifications_changed); } else if (name == "disable_top_chats") { send_closure(top_dialog_manager_, &TopDialogManager::update_is_enabled, !G()->shared_config().get_option_boolean(name)); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ca4c6e43..d282cdef 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -806,8 +806,8 @@ class CliClient final : public Actor { td_api::make_object(1))); send_request(td_api::make_object("use_storage_optimizer", td_api::make_object(false))); - send_request( - td_api::make_object("online", td_api::make_object(true))); + send_request(td_api::make_object( + "use_pfs", td_api::make_object(std::time(nullptr) / 86400 % 2 == 0))); send_request(td_api::make_object(td_api::make_object())); send_request(td_api::make_object()); @@ -824,6 +824,8 @@ class CliClient final : public Actor { bad_parameters->api_hash_ = api_hash_; send_request(td_api::make_object(std::move(bad_parameters))); } + send_request(td_api::make_object("disable_contact_registered_notifications", + td_api::make_object(true))); } void init() {