2018-11-09 15:14:02 +01:00
|
|
|
//
|
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
|
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
2018-11-09 23:56:00 +01:00
|
|
|
#include "td/telegram/DialogId.h"
|
2018-11-20 15:08:44 +01:00
|
|
|
#include "td/telegram/MessageId.h"
|
2018-11-10 00:08:47 +01:00
|
|
|
#include "td/telegram/NotificationGroupId.h"
|
|
|
|
#include "td/telegram/NotificationId.h"
|
2018-11-09 23:56:00 +01:00
|
|
|
#include "td/telegram/NotificationType.h"
|
2018-11-15 16:58:33 +01:00
|
|
|
#include "td/telegram/td_api.h"
|
2018-11-09 23:56:00 +01:00
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
#include "td/actor/actor.h"
|
2018-11-09 15:14:02 +01:00
|
|
|
#include "td/actor/PromiseFuture.h"
|
2018-11-15 16:58:33 +01:00
|
|
|
#include "td/actor/Timeout.h"
|
2018-11-09 15:14:02 +01:00
|
|
|
|
2018-11-09 23:56:00 +01:00
|
|
|
#include "td/utils/common.h"
|
2018-11-15 16:58:33 +01:00
|
|
|
#include "td/utils/StringBuilder.h"
|
|
|
|
|
2018-11-22 18:17:26 +01:00
|
|
|
#include <functional>
|
2018-11-15 16:58:33 +01:00
|
|
|
#include <map>
|
2018-11-21 23:28:56 +01:00
|
|
|
#include <unordered_map>
|
2018-11-09 23:56:00 +01:00
|
|
|
|
2018-11-09 15:14:02 +01:00
|
|
|
namespace td {
|
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
extern int VERBOSITY_NAME(notifications);
|
|
|
|
|
2018-11-09 15:14:02 +01:00
|
|
|
class Td;
|
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
class NotificationManager : public Actor {
|
2018-11-09 15:14:02 +01:00
|
|
|
public:
|
2018-11-15 16:58:33 +01:00
|
|
|
static constexpr int32 MIN_NOTIFICATION_GROUP_COUNT_MAX = 1;
|
|
|
|
static constexpr int32 MAX_NOTIFICATION_GROUP_COUNT_MAX = 25;
|
|
|
|
static constexpr int32 MIN_NOTIFICATION_GROUP_SIZE_MAX = 1;
|
|
|
|
static constexpr int32 MAX_NOTIFICATION_GROUP_SIZE_MAX = 25;
|
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
NotificationManager(Td *td, ActorShared<> parent);
|
2018-11-09 15:14:02 +01:00
|
|
|
|
2018-11-17 22:24:19 +01:00
|
|
|
NotificationId get_max_notification_id() const;
|
|
|
|
|
2018-11-10 00:08:47 +01:00
|
|
|
NotificationId get_next_notification_id();
|
2018-11-09 23:56:00 +01:00
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
NotificationGroupId get_next_notification_group_id();
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
void add_notification(NotificationGroupId group_id, DialogId dialog_id, int32 date,
|
|
|
|
DialogId notification_settings_dialog_id, bool is_silent, NotificationId notification_id,
|
|
|
|
unique_ptr<NotificationType> type);
|
2018-11-09 23:56:00 +01:00
|
|
|
|
2018-11-16 16:00:46 +01:00
|
|
|
void edit_notification(NotificationGroupId group_id, NotificationId notification_id,
|
|
|
|
unique_ptr<NotificationType> type);
|
2018-11-09 23:56:00 +01:00
|
|
|
|
2018-11-20 14:11:34 +01:00
|
|
|
void remove_notification(NotificationGroupId group_id, NotificationId notification_id, bool is_permanent,
|
|
|
|
Promise<Unit> &&promise);
|
2018-11-09 15:14:02 +01:00
|
|
|
|
2018-11-10 00:08:47 +01:00
|
|
|
void remove_notification_group(NotificationGroupId group_id, NotificationId max_notification_id,
|
2018-11-20 15:08:44 +01:00
|
|
|
MessageId max_message_id, int32 new_total_count, Promise<Unit> &&promise);
|
2018-11-09 15:14:02 +01:00
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
void on_notification_group_count_max_changed();
|
|
|
|
|
|
|
|
void on_notification_group_size_max_changed();
|
|
|
|
|
2018-11-15 23:03:04 +01:00
|
|
|
void on_online_cloud_timeout_changed();
|
|
|
|
|
|
|
|
void on_notification_cloud_delay_changed();
|
|
|
|
|
|
|
|
void on_notification_default_delay_changed();
|
|
|
|
|
2018-11-22 02:00:28 +01:00
|
|
|
void before_get_difference();
|
|
|
|
|
|
|
|
void after_get_difference();
|
|
|
|
|
|
|
|
void before_get_chat_difference(NotificationGroupId group_id);
|
|
|
|
|
|
|
|
void after_get_chat_difference(NotificationGroupId group_id);
|
|
|
|
|
2018-11-09 15:14:02 +01:00
|
|
|
private:
|
2018-11-15 16:58:33 +01:00
|
|
|
static constexpr int32 DEFAULT_GROUP_COUNT_MAX = 10;
|
|
|
|
static constexpr int32 DEFAULT_GROUP_SIZE_MAX = 10;
|
|
|
|
static constexpr size_t EXTRA_GROUP_SIZE = 10;
|
|
|
|
|
|
|
|
static constexpr int32 DEFAULT_ONLINE_CLOUD_TIMEOUT_MS = 300000;
|
|
|
|
static constexpr int32 DEFAULT_ONLINE_CLOUD_DELAY_MS = 30000;
|
|
|
|
static constexpr int32 DEFAULT_DEFAULT_DELAY_MS = 1500;
|
|
|
|
|
|
|
|
static constexpr int32 MIN_NOTIFICATION_DELAY_MS = 1;
|
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
static constexpr int32 MIN_UPDATE_DELAY_MS = 50;
|
|
|
|
static constexpr int32 MAX_UPDATE_DELAY_MS = 60000;
|
|
|
|
|
2018-11-12 15:44:42 +01:00
|
|
|
struct Notification {
|
|
|
|
NotificationId notification_id;
|
2018-11-20 14:11:34 +01:00
|
|
|
int32 date = 0;
|
2018-11-12 15:44:42 +01:00
|
|
|
unique_ptr<NotificationType> type;
|
2018-11-15 16:58:33 +01:00
|
|
|
|
2018-11-20 14:11:34 +01:00
|
|
|
Notification(NotificationId notification_id, int32 date, unique_ptr<NotificationType> type)
|
|
|
|
: notification_id(notification_id), date(date), type(std::move(type)) {
|
2018-11-15 16:58:33 +01:00
|
|
|
}
|
2018-11-12 15:44:42 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct PendingNotification {
|
2018-11-15 16:58:33 +01:00
|
|
|
int32 date = 0;
|
2018-11-12 15:44:42 +01:00
|
|
|
DialogId settings_dialog_id;
|
2018-11-15 16:58:33 +01:00
|
|
|
bool is_silent = false;
|
2018-11-12 15:44:42 +01:00
|
|
|
NotificationId notification_id;
|
|
|
|
unique_ptr<NotificationType> type;
|
|
|
|
};
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
struct NotificationGroupKey {
|
|
|
|
NotificationGroupId group_id;
|
2018-11-12 15:44:42 +01:00
|
|
|
DialogId dialog_id;
|
2018-11-15 16:58:33 +01:00
|
|
|
int32 last_notification_date = 0;
|
|
|
|
|
|
|
|
bool operator<(const NotificationGroupKey &other) const {
|
|
|
|
if (last_notification_date != other.last_notification_date) {
|
|
|
|
return last_notification_date > other.last_notification_date;
|
|
|
|
}
|
|
|
|
if (dialog_id != other.dialog_id) {
|
|
|
|
return dialog_id.get() > other.dialog_id.get();
|
|
|
|
}
|
|
|
|
return group_id.get() > other.group_id.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
friend StringBuilder &operator<<(StringBuilder &string_builder, const NotificationGroupKey &group_key) {
|
|
|
|
return string_builder << '[' << group_key.group_id << ',' << group_key.dialog_id << ','
|
|
|
|
<< group_key.last_notification_date << ']';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
struct NotificationGroup {
|
2018-11-12 15:44:42 +01:00
|
|
|
int32 total_count = 0;
|
|
|
|
|
|
|
|
vector<Notification> notifications;
|
2018-11-15 16:58:33 +01:00
|
|
|
|
|
|
|
double pending_notifications_flush_time = 0;
|
2018-11-12 15:44:42 +01:00
|
|
|
vector<PendingNotification> pending_notifications;
|
|
|
|
};
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
using NotificationGroups = std::map<NotificationGroupKey, NotificationGroup>;
|
|
|
|
|
|
|
|
static void on_flush_pending_notifications_timeout_callback(void *notification_manager_ptr, int64 group_id_int);
|
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
static void on_flush_pending_updates_timeout_callback(void *notification_manager_ptr, int64 group_id_int);
|
|
|
|
|
2018-11-12 15:44:42 +01:00
|
|
|
bool is_disabled() const;
|
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
void start_up() override;
|
|
|
|
void tear_down() override;
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
static td_api::object_ptr<td_api::notification> get_notification_object(DialogId dialog_id,
|
|
|
|
const Notification ¬ification);
|
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
void add_update(int32 group_id, td_api::object_ptr<td_api::Update> update);
|
|
|
|
|
|
|
|
void add_update_notification_group(td_api::object_ptr<td_api::updateNotificationGroup> update);
|
2018-11-15 16:58:33 +01:00
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
void add_update_notification(NotificationGroupId notification_group_id, DialogId dialog_id,
|
|
|
|
const Notification ¬ification);
|
2018-11-16 16:00:46 +01:00
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
NotificationGroups::iterator get_group(NotificationGroupId group_id);
|
|
|
|
|
|
|
|
NotificationGroupKey get_last_updated_group_key() const;
|
|
|
|
|
2018-11-21 16:00:14 +01:00
|
|
|
void send_remove_group_update(const NotificationGroupKey &group_key, const NotificationGroup &group,
|
|
|
|
vector<int32> &&removed_notification_ids);
|
2018-11-15 16:58:33 +01:00
|
|
|
|
|
|
|
void send_add_group_update(const NotificationGroupKey &group_key, const NotificationGroup &group);
|
|
|
|
|
|
|
|
int32 get_notification_delay_ms(DialogId dialog_id, const PendingNotification ¬ification) const;
|
|
|
|
|
2018-11-21 13:23:43 +01:00
|
|
|
void do_flush_pending_notifications(NotificationGroupKey &group_key, NotificationGroup &group,
|
|
|
|
vector<PendingNotification> &pending_notifications);
|
2018-11-15 16:58:33 +01:00
|
|
|
|
|
|
|
void flush_pending_notifications(NotificationGroupId group_id);
|
|
|
|
|
2018-11-20 14:11:34 +01:00
|
|
|
void on_notifications_removed(NotificationGroups::iterator &&group_it,
|
|
|
|
vector<td_api::object_ptr<td_api::notification>> &&added_notifications,
|
|
|
|
vector<int32> &&removed_notification_ids);
|
|
|
|
|
2018-11-22 18:17:26 +01:00
|
|
|
void remove_added_notifications_from_pending_updates(
|
|
|
|
NotificationGroupId group_id,
|
|
|
|
std::function<bool(const td_api::object_ptr<td_api::notification> ¬ification)> is_removed);
|
|
|
|
|
2018-11-23 12:42:34 +01:00
|
|
|
void flush_pending_updates(int32 group_id, const char *source);
|
2018-11-21 23:28:56 +01:00
|
|
|
|
2018-11-11 13:58:52 +01:00
|
|
|
NotificationId current_notification_id_;
|
|
|
|
NotificationGroupId current_notification_group_id_;
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
size_t max_notification_group_count_ = 0;
|
|
|
|
size_t max_notification_group_size_ = 0;
|
|
|
|
size_t keep_notification_group_size_ = 0;
|
|
|
|
|
|
|
|
int32 online_cloud_timeout_ms_ = DEFAULT_ONLINE_CLOUD_TIMEOUT_MS;
|
|
|
|
int32 notification_cloud_delay_ms_ = DEFAULT_ONLINE_CLOUD_DELAY_MS;
|
|
|
|
int32 notification_default_delay_ms_ = DEFAULT_DEFAULT_DELAY_MS;
|
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
bool running_get_difference_ = false;
|
2018-11-22 02:00:28 +01:00
|
|
|
std::unordered_set<int32> running_get_chat_difference_;
|
2018-11-21 23:28:56 +01:00
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
NotificationGroups groups_;
|
2018-11-12 15:44:42 +01:00
|
|
|
|
2018-11-21 23:28:56 +01:00
|
|
|
std::unordered_map<int32, vector<td_api::object_ptr<td_api::Update>>> pending_updates_;
|
|
|
|
|
2018-11-23 12:42:34 +01:00
|
|
|
void after_get_difference_impl();
|
|
|
|
|
|
|
|
void after_get_chat_difference_impl(NotificationGroupId group_id);
|
|
|
|
|
2018-11-15 16:58:33 +01:00
|
|
|
MultiTimeout flush_pending_notifications_timeout_{"FlushPendingNotificationsTimeout"};
|
2018-11-21 23:28:56 +01:00
|
|
|
MultiTimeout flush_pending_updates_timeout_{"FlushPendingUpdatesTimeout"};
|
2018-11-12 15:44:42 +01:00
|
|
|
|
2018-11-09 15:14:02 +01:00
|
|
|
Td *td_;
|
2018-11-11 13:58:52 +01:00
|
|
|
ActorShared<> parent_;
|
2018-11-09 15:14:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace td
|