diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 6eab30472..1c2f5e11d 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -246,6 +246,28 @@ void NotificationManager::init() { } } + auto notification_announcement_ids_string = G()->td_db()->get_binlog_pmc()->get("notification_announcement_ids"); + if (!notification_announcement_ids_string.empty()) { + VLOG(notifications) << "Load announcement ids = " << notification_announcement_ids_string; + auto ids = transform(full_split(notification_announcement_ids_string, ','), + [](Slice str) { return to_integer_safe(str).ok(); }); + CHECK(ids.size() % 2 == 0); + bool is_changed = false; + auto min_date = G()->unix_time() - ANNOUNCEMENT_ID_CACHE_TIME; + for (size_t i = 0; i < ids.size(); i += 2) { + auto id = ids[i]; + auto date = ids[i + 1]; + if (date < min_date) { + is_changed = true; + continue; + } + announcement_id_date_.emplace(id, date); + } + if (is_changed) { + save_announcement_ids(); + } + } + class StateCallback : public StateManager::Callback { public: explicit StateCallback(ActorId parent) : parent_(std::move(parent)) { @@ -263,6 +285,29 @@ void NotificationManager::init() { send_closure(G()->state_manager(), &StateManager::add_callback, make_unique(actor_id(this))); } +void NotificationManager::save_announcement_ids() { + auto min_date = G()->unix_time() - ANNOUNCEMENT_ID_CACHE_TIME; + vector ids; + for (auto &it : announcement_id_date_) { + auto id = it.first; + auto date = it.second; + if (date < min_date) { + continue; + } + ids.push_back(id); + ids.push_back(date); + } + + VLOG(notifications) << "Save announcement ids " << ids; + if (ids.empty()) { + G()->td_db()->get_binlog_pmc()->erase("notification_announcement_ids"); + return; + } + + auto notification_announcement_ids_string = implode(transform(ids, [](int32 id) { return to_string(id); }), ','); + G()->td_db()->get_binlog_pmc()->set("notification_announcement_ids", notification_announcement_ids_string); +} + td_api::object_ptr NotificationManager::get_update_active_notifications() const { auto needed_groups = max_notification_group_count_; vector> groups; @@ -2261,7 +2306,7 @@ void NotificationManager::process_push_notification(string payload, Promiseget_my_id()) { auto status = process_push_notification_payload(payload); if (status.is_error()) { LOG(ERROR) << "Receive error " << status << ", while parsing push payload " << payload; @@ -2332,11 +2377,20 @@ Status NotificationManager::process_push_notification_payload(string payload) { if (announcement_message_text.empty()) { return Status::Error("Have empty announcement message text"); } + TRY_RESULT(announcement_id, get_json_object_int_field(custom, "announcement")); + auto &date = announcement_id_date_[announcement_id]; + auto now = G()->unix_time(); + if (date >= now - ANNOUNCEMENT_ID_CACHE_TIME) { + VLOG(notifications) << "Ignore duplicate announcement " << announcement_id; + return Status::OK(); + } + date = now; auto update = telegram_api::make_object( telegram_api::updateServiceNotification::INBOX_DATE_MASK, false, G()->unix_time(), string(), announcement_message_text, nullptr, vector>()); send_closure(G()->messages_manager(), &MessagesManager::on_update_service_notification, std::move(update), false); + save_announcement_ids(); return Status::OK(); } if (!announcement_message_text.empty()) { @@ -2347,7 +2401,7 @@ Status NotificationManager::process_push_notification_payload(string payload) { TRY_RESULT(dc_id, get_json_object_int_field(custom, "dc", false)); TRY_RESULT(addr, get_json_object_string_field(custom, "addr", false)); if (!DcId::is_valid(dc_id)) { - return Status::Error("Invalid dc id"); + return Status::Error("Invalid datacenter ID"); } if (!clean_input_string(addr)) { return Status::Error(PSLICE() << "Receive invalid addr " << format::escaped(addr)); @@ -2553,7 +2607,7 @@ Result NotificationManager::get_push_receiver_id(string payload) { } } - return Status::Error(200, "Unsupported push notification"); + return static_cast(0); } Result NotificationManager::decrypt_push(int64 encryption_key_id, string encryption_key, string push) { diff --git a/td/telegram/NotificationManager.h b/td/telegram/NotificationManager.h index c49b2d42e..e0f89e58c 100644 --- a/td/telegram/NotificationManager.h +++ b/td/telegram/NotificationManager.h @@ -135,6 +135,8 @@ class NotificationManager : public Actor { static constexpr int32 MIN_UPDATE_DELAY_MS = 50; static constexpr int32 MAX_UPDATE_DELAY_MS = 60000; + static constexpr int32 ANNOUNCEMENT_ID_CACHE_TIME = 7 * 86400; + struct PendingNotification { int32 date = 0; DialogId settings_dialog_id; @@ -273,6 +275,8 @@ class NotificationManager : public Actor { void on_contact_registered_notifications_sync(bool is_disabled, Result result); + void save_announcement_ids(); + NotificationId current_notification_id_; NotificationGroupId current_notification_group_id_; @@ -314,6 +318,8 @@ class NotificationManager : public Actor { }; std::unordered_map, DialogIdHash> active_call_notifications_; + std::unordered_map announcement_id_date_; + Td *td_; ActorShared<> parent_; };