Ignore duplicate announcements.

GitOrigin-RevId: e09927a5dbae88001a6674e5155d1cffdb57e810
This commit is contained in:
levlam 2019-03-26 22:32:07 +03:00
parent 7fe4ebfc24
commit 1e1b24dfb3
2 changed files with 63 additions and 3 deletions

View File

@ -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<int32>(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 { class StateCallback : public StateManager::Callback {
public: public:
explicit StateCallback(ActorId<NotificationManager> parent) : parent_(std::move(parent)) { explicit StateCallback(ActorId<NotificationManager> parent) : parent_(std::move(parent)) {
@ -263,6 +285,29 @@ void NotificationManager::init() {
send_closure(G()->state_manager(), &StateManager::add_callback, make_unique<StateCallback>(actor_id(this))); send_closure(G()->state_manager(), &StateManager::add_callback, make_unique<StateCallback>(actor_id(this)));
} }
void NotificationManager::save_announcement_ids() {
auto min_date = G()->unix_time() - ANNOUNCEMENT_ID_CACHE_TIME;
vector<int32> 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<td_api::updateActiveNotifications> NotificationManager::get_update_active_notifications() const { td_api::object_ptr<td_api::updateActiveNotifications> NotificationManager::get_update_active_notifications() const {
auto needed_groups = max_notification_group_count_; auto needed_groups = max_notification_group_count_;
vector<td_api::object_ptr<td_api::notificationGroup>> groups; vector<td_api::object_ptr<td_api::notificationGroup>> groups;
@ -2261,7 +2306,7 @@ void NotificationManager::process_push_notification(string payload, Promise<Unit
break; break;
} }
} }
if (receiver_id == 0) { if (receiver_id == 0 || receiver_id == G()->get_my_id()) {
auto status = process_push_notification_payload(payload); auto status = process_push_notification_payload(payload);
if (status.is_error()) { if (status.is_error()) {
LOG(ERROR) << "Receive error " << status << ", while parsing push payload " << payload; 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()) { if (announcement_message_text.empty()) {
return Status::Error("Have empty announcement message text"); 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>( auto update = telegram_api::make_object<telegram_api::updateServiceNotification>(
telegram_api::updateServiceNotification::INBOX_DATE_MASK, false, G()->unix_time(), string(), telegram_api::updateServiceNotification::INBOX_DATE_MASK, false, G()->unix_time(), string(),
announcement_message_text, nullptr, vector<telegram_api::object_ptr<telegram_api::MessageEntity>>()); announcement_message_text, nullptr, vector<telegram_api::object_ptr<telegram_api::MessageEntity>>());
send_closure(G()->messages_manager(), &MessagesManager::on_update_service_notification, std::move(update), false); send_closure(G()->messages_manager(), &MessagesManager::on_update_service_notification, std::move(update), false);
save_announcement_ids();
return Status::OK(); return Status::OK();
} }
if (!announcement_message_text.empty()) { 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(dc_id, get_json_object_int_field(custom, "dc", false));
TRY_RESULT(addr, get_json_object_string_field(custom, "addr", false)); TRY_RESULT(addr, get_json_object_string_field(custom, "addr", false));
if (!DcId::is_valid(dc_id)) { if (!DcId::is_valid(dc_id)) {
return Status::Error("Invalid dc id"); return Status::Error("Invalid datacenter ID");
} }
if (!clean_input_string(addr)) { if (!clean_input_string(addr)) {
return Status::Error(PSLICE() << "Receive invalid addr " << format::escaped(addr)); return Status::Error(PSLICE() << "Receive invalid addr " << format::escaped(addr));
@ -2553,7 +2607,7 @@ Result<int64> NotificationManager::get_push_receiver_id(string payload) {
} }
} }
return Status::Error(200, "Unsupported push notification"); return static_cast<int64>(0);
} }
Result<string> NotificationManager::decrypt_push(int64 encryption_key_id, string encryption_key, string push) { Result<string> NotificationManager::decrypt_push(int64 encryption_key_id, string encryption_key, string push) {

View File

@ -135,6 +135,8 @@ class NotificationManager : public Actor {
static constexpr int32 MIN_UPDATE_DELAY_MS = 50; static constexpr int32 MIN_UPDATE_DELAY_MS = 50;
static constexpr int32 MAX_UPDATE_DELAY_MS = 60000; static constexpr int32 MAX_UPDATE_DELAY_MS = 60000;
static constexpr int32 ANNOUNCEMENT_ID_CACHE_TIME = 7 * 86400;
struct PendingNotification { struct PendingNotification {
int32 date = 0; int32 date = 0;
DialogId settings_dialog_id; DialogId settings_dialog_id;
@ -273,6 +275,8 @@ class NotificationManager : public Actor {
void on_contact_registered_notifications_sync(bool is_disabled, Result<Unit> result); void on_contact_registered_notifications_sync(bool is_disabled, Result<Unit> result);
void save_announcement_ids();
NotificationId current_notification_id_; NotificationId current_notification_id_;
NotificationGroupId current_notification_group_id_; NotificationGroupId current_notification_group_id_;
@ -314,6 +318,8 @@ class NotificationManager : public Actor {
}; };
std::unordered_map<DialogId, vector<ActiveCallNotification>, DialogIdHash> active_call_notifications_; std::unordered_map<DialogId, vector<ActiveCallNotification>, DialogIdHash> active_call_notifications_;
std::unordered_map<int32, int32> announcement_id_date_;
Td *td_; Td *td_;
ActorShared<> parent_; ActorShared<> parent_;
}; };