diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index cab1e4c7..ec7e7b91 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -482,23 +482,24 @@ messages total_count:int32 messages:vector = Messages; foundMessages messages:vector next_from_search_id:int64 = FoundMessages; -//@class NotificationSettingsScope @description Describes the types of chats for which notification settings are applied +//@class NotificationSettingsScope @description Describes the types of chats for which scope notification settings are applied -//@description Notification settings applied to a particular chat @chat_id Chat identifier -notificationSettingsScopeChat chat_id:int53 = NotificationSettingsScope; - -//@description Notification settings applied to all private chats +//@description Notification settings applied to all private and secret chats when corresponding chat setting has a default value notificationSettingsScopePrivateChats = NotificationSettingsScope; -//@description Notification settings applied to all basic groups and channels. (Supergroups have no common settings) -notificationSettingsScopeBasicGroupChats = NotificationSettingsScope; - -//@description Notification settings applied to all chats -notificationSettingsScopeAllChats = NotificationSettingsScope; +//@description Notification settings applied to all basic groups, supergroups and channels when corresponding chat setting has a default value +notificationSettingsScopeGroupChats = NotificationSettingsScope; -//@description Contains information about notification settings for a chat or several chats @mute_for Time left before notifications will be unmuted, in seconds @sound An audio file name for notification sounds; only applies to iOS applications @show_preview True, if message content should be displayed in notifications -notificationSettings mute_for:int32 sound:string show_preview:Bool = NotificationSettings; +//@description Contains information about notification settings for a chat +//@use_default_mute_for If true, mute_for is ignored and value from a surrounding scope is used instead @mute_for Time left before notifications will be unmuted, in seconds +//@use_default_sound If true, sound is ignored and value from a surrounding scope is used instead @sound An audio file name for notification sounds; only applies to iOS applications +//@use_default_show_preview If true, show_preview is ignored and value from a surrounding scope is used instead @show_preview True, if message content should be displayed in notifications +chatNotificationSettings use_default_mute_for:Bool mute_for:int32 use_default_sound:Bool sound:string use_default_show_preview:Bool show_preview:Bool = ChatNotificationSettings; + +//@description Contains information about notification settings for several chats @mute_for Time left before notifications will be unmuted, in seconds +//@sound An audio file name for notification sounds; only applies to iOS applications @show_preview True, if message content should be displayed in notifications +scopeNotificationSettings mute_for:int32 sound:string show_preview:Bool = ScopeNotificationSettings; //@description Contains information about a message draft @reply_to_message_id Identifier of the message to reply to; 0 if none @input_message_text Content of the message draft; this should always be of type inputMessageText @@ -537,7 +538,7 @@ chatTypeSecret secret_chat_id:int32 user_id:int32 = ChatType; //@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat //@draft_message A draft of a message in the chat; may be null //@client_data Contains client-specific data associated with the chat. (For example, the chat position or local chat notification settings can be stored here.) Persistent if a message database is used -chat id:int53 type:ChatType title:string photo:chatPhoto last_message:message order:int64 is_pinned:Bool can_be_reported:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:notificationSettings reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; +chat id:int53 type:ChatType title:string photo:chatPhoto last_message:message order:int64 is_pinned:Bool can_be_reported:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:chatNotificationSettings reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat; //@description Represents a list of chats @chat_ids List of chat identifiers chats chat_ids:vector = Chats; @@ -1904,8 +1905,11 @@ updateChatReadOutbox chat_id:int53 last_read_outbox_message_id:int53 = Update; //@description The chat unread_mention_count has changed @chat_id Chat identifier @unread_mention_count The number of unread mention messages left in the chat updateChatUnreadMentionCount chat_id:int53 unread_mention_count:int32 = Update; -//@description Notification settings for some chats were updated @scope Types of chats for which notification settings were updated @notification_settings The new notification settings -updateNotificationSettings scope:NotificationSettingsScope notification_settings:notificationSettings = Update; +//@description Notification settings for a chat were changed @chat_id Chat identifier @notification_settings The new notification settings +updateChatNotificationSettings chat_id:int53 notification_settings:chatNotificationSettings = Update; + +//@description Notification settings for some chats scope were updated @scope Types of chats for which notification settings were updated @notification_settings The new notification settings +updateScopeNotificationSettings scope:NotificationSettingsScope notification_settings:scopeNotificationSettings = Update; //@description The default chat reply markup was changed. Can occur because new messages with reply markup were received or because an old reply markup was hidden by the user //@chat_id Chat identifier @reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat @@ -2450,6 +2454,9 @@ setChatPhoto chat_id:int53 photo:InputFile = Ok; //@description Changes the draft message in a chat @chat_id Chat identifier @draft_message New draft message; may be null setChatDraftMessage chat_id:int53 draft_message:draftMessage = Ok; +//@description Changes notification settings of a chat @chat_id Chat identifier @notification_settings The new notification settings for the chat +setChatNotificationSettings chat_id:int53 notification_settings:chatNotificationSettings = Ok; + //@description Changes the pinned state of a chat. You can pin up to GetOption("pinned_chat_count_max") non-secret chats and the same number of secret chats @chat_id Chat identifier @is_pinned New value of is_pinned toggleChatIsPinned chat_id:int53 is_pinned:Bool = Ok; @@ -2478,6 +2485,16 @@ searchChatMembers chat_id:int53 query:string limit:int32 = ChatMembers; getChatAdministrators chat_id:int53 = Users; +//@description Returns the notification settings for a given scope @scope Scope for which to return the notification settings information +getScopeNotificationSettings scope:NotificationSettingsScope = ScopeNotificationSettings; + +//@description Changes notification settings for a given scope @scope Scope for which to change the notification settings @notification_settings The new notification settings for the given scope +setScopeNotificationSettings scope:NotificationSettingsScope notification_settings:scopeNotificationSettings = Ok; + +//@description Resets all notification settings to their default values. By default, all chats are unmuted, the sound is set to "default" and message previews are shown +resetAllNotificationSettings = Ok; + + //@description Changes the order of pinned chats @chat_ids The new list of pinned chats setPinnedChats chat_ids:vector = Ok; @@ -2669,17 +2686,6 @@ getWebPagePreview text:formattedText = WebPage; getWebPageInstantView url:string force_full:Bool = WebPageInstantView; -//@description Returns the notification settings for a given scope @scope Scope for which to return the notification settings information -getNotificationSettings scope:NotificationSettingsScope = NotificationSettings; - -//@description Changes notification settings for a given scope @scope Scope for which to change the notification settings -//@notification_settings The new notification settings for the given scope -setNotificationSettings scope:NotificationSettingsScope notification_settings:notificationSettings = Ok; - -//@description Resets all notification settings to their default values. By default, the only muted chats are supergroups, the sound is set to "default" and message previews are shown -resetAllNotificationSettings = Ok; - - //@description Uploads a new profile photo for the current user. If something changes, updateUser will be sent @photo Profile photo to set. inputFileId and inputFileRemote may still be unsupported setProfilePhoto photo:InputFile = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 681ae813..6aad0f7e 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index edab392f..5b893997 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -183,18 +183,10 @@ auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorizat inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer; inputNotifyUsers#193b4417 = InputNotifyPeer; inputNotifyChats#4a95e84e = InputNotifyPeer; -inputNotifyAll#a429b886 = InputNotifyPeer; -inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents; -inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents; +inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings; -inputPeerNotifySettings#38935eb2 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = InputPeerNotifySettings; - -peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents; -peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents; - -peerNotifySettingsEmpty#70a68512 = PeerNotifySettings; -peerNotifySettings#9acda4c0 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = PeerNotifySettings; +peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings; peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings; @@ -395,7 +387,6 @@ help.support#17c6b5f6 phone_number:string user:User = help.Support; notifyPeer#9fd40bd8 peer:Peer = NotifyPeer; notifyUsers#b4c83b4c = NotifyPeer; notifyChats#c007cec3 = NotifyPeer; -notifyAll#74d07c60 = NotifyPeer; sendMessageTypingAction#16bf744e = SendMessageAction; sendMessageCancelAction#fd5ec8f5 = SendMessageAction; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index 1ef5b461..c1a219c4 100644 Binary files a/td/generate/scheme/telegram_api.tlo and b/td/generate/scheme/telegram_api.tlo differ diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 689016a1..90bc0826 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6265,7 +6265,7 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u } on_update_user_links(user_id, std::move(user_full->link_->my_link_), std::move(user_full->link_->foreign_link_)); - td_->messages_manager_->on_update_notify_settings(DialogId(user_id).get(), std::move(user_full->notify_settings_)); + td_->messages_manager_->on_update_dialog_notify_settings(DialogId(user_id), std::move(user_full->notify_settings_)); UserFull *user = &users_full_[user_id]; user->expires_at = Time::now() + USER_FULL_EXPIRE_TIME; @@ -6438,7 +6438,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c } on_get_chat_participants(std::move(chat_full->participants_)); - td_->messages_manager_->on_update_notify_settings(DialogId(chat_id).get(), std::move(chat_full->notify_settings_)); + td_->messages_manager_->on_update_dialog_notify_settings(DialogId(chat_id), std::move(chat_full->notify_settings_)); update_chat_full(chat, chat_id); } else { @@ -6450,8 +6450,8 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c return; } - td_->messages_manager_->on_update_notify_settings(DialogId(channel_id).get(), - std::move(channel_full->notify_settings_)); + td_->messages_manager_->on_update_dialog_notify_settings(DialogId(channel_id), + std::move(channel_full->notify_settings_)); // Ignoring channel_full->photo diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 44a110c4..284e581f 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -2793,8 +2793,9 @@ class SetTypingQuery : public Td::ResultHandler { return promise_.set_value(Unit()); } - LOG(INFO) << "Receive error for set typing: " << status; - td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery"); + if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery")) { + LOG(INFO) << "Receive error for set typing: " << status; + } promise_.set_error(std::move(status)); } }; @@ -2910,12 +2911,46 @@ class DeleteChannelMessagesQuery : public Td::ResultHandler { } }; -class GetNotifySettingsQuery : public Td::ResultHandler { +class GetDialogNotifySettingsQuery : public Td::ResultHandler { + Promise promise_; + DialogId dialog_id_; + + public: + explicit GetDialogNotifySettingsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id) { + dialog_id_ = dialog_id; + auto input_notify_peer = td->messages_manager_->get_input_notify_peer(dialog_id); + CHECK(input_notify_peer != nullptr); + send_query(G()->net_query_creator().create( + create_storer(telegram_api::account_getNotifySettings(std::move(input_notify_peer))))); + } + + 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()); + } + + auto ptr = result_ptr.move_as_ok(); + td->messages_manager_->on_update_dialog_notify_settings(dialog_id_, std::move(ptr)); + + promise_.set_value(Unit()); + } + + void on_error(uint64 id, Status status) override { + td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetDialogNotifySettingsQuery"); + promise_.set_error(std::move(status)); + } +}; + +class GetScopeNotifySettingsQuery : public Td::ResultHandler { Promise promise_; NotificationSettingsScope scope_; public: - explicit GetNotifySettingsQuery(Promise &&promise) : promise_(std::move(promise)) { + explicit GetScopeNotifySettingsQuery(Promise &&promise) : promise_(std::move(promise)) { } void send(NotificationSettingsScope scope) { @@ -2933,7 +2968,7 @@ class GetNotifySettingsQuery : public Td::ResultHandler { } auto ptr = result_ptr.move_as_ok(); - td->messages_manager_->on_update_notify_settings(scope_, std::move(ptr)); + td->messages_manager_->on_update_scope_notify_settings(scope_, std::move(ptr)); promise_.set_value(Unit()); } @@ -2943,25 +2978,80 @@ class GetNotifySettingsQuery : public Td::ResultHandler { } }; -class UpdateNotifySettingsQuery : public Td::ResultHandler { - NotificationSettingsScope scope_; +class UpdateDialogNotifySettingsQuery : public Td::ResultHandler { + DialogId dialog_id_; public: - void send(NotificationSettingsScope scope, const NotificationSettings &new_settings) { - auto input_notify_peer = td->messages_manager_->get_input_notify_peer(scope); + void send(DialogId dialog_id, const DialogNotificationSettings &new_settings) { + auto input_notify_peer = td->messages_manager_->get_input_notify_peer(dialog_id); if (input_notify_peer == nullptr) { return; } int32 flags = 0; - if (new_settings.show_preview) { + if (!new_settings.use_default_mute_until) { + flags |= telegram_api::inputPeerNotifySettings::MUTE_UNTIL_MASK; + } + if (!new_settings.use_default_sound) { + flags |= telegram_api::inputPeerNotifySettings::SOUND_MASK; + } + if (!new_settings.use_default_show_preview) { flags |= telegram_api::inputPeerNotifySettings::SHOW_PREVIEWS_MASK; } if (new_settings.silent_send_message) { flags |= telegram_api::inputPeerNotifySettings::SILENT_MASK; } + send_query(G()->net_query_creator().create(create_storer(telegram_api::account_updateNotifySettings( + std::move(input_notify_peer), make_tl_object( + flags, new_settings.show_preview, new_settings.silent_send_message, + new_settings.mute_until, new_settings.sound))))); + dialog_id_ = dialog_id; + } + + 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()); + } + + bool result = result_ptr.ok(); + if (!result) { + return on_error(id, Status::Error(400, "Receive false as result")); + } + } + + void on_error(uint64 id, Status status) override { + if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "UpdateDialogNotifySettingsQuery")) { + LOG(INFO) << "Receive error for set chat notification settings: " << status; + status.ignore(); + } + + if (!td->auth_manager_->is_bot() && td->messages_manager_->get_input_notify_peer(dialog_id_) != nullptr) { + // trying to repair notification settings for this dialog + td->create_handler(Promise<>())->send(dialog_id_); + } + } +}; + +class UpdateScopeNotifySettingsQuery : public Td::ResultHandler { + NotificationSettingsScope scope_; + + public: + void send(NotificationSettingsScope scope, const ScopeNotificationSettings &new_settings) { + auto input_notify_peer = td->messages_manager_->get_input_notify_peer(scope); + CHECK(input_notify_peer != nullptr); + int32 flags = 0; + if (new_settings.mute_until != 0) { + flags |= telegram_api::inputPeerNotifySettings::MUTE_UNTIL_MASK; + } + if (new_settings.sound != "default") { + flags |= telegram_api::inputPeerNotifySettings::SOUND_MASK; + } + if (new_settings.show_preview) { + flags |= telegram_api::inputPeerNotifySettings::SHOW_PREVIEWS_MASK; + } send_query(G()->net_query_creator().create(create_storer(telegram_api::account_updateNotifySettings( std::move(input_notify_peer), - make_tl_object(flags, false /*ignored*/, false /*ignored*/, + make_tl_object(flags, new_settings.show_preview, false, new_settings.mute_until, new_settings.sound))))); scope_ = scope; } @@ -2982,9 +3072,9 @@ class UpdateNotifySettingsQuery : public Td::ResultHandler { LOG(INFO) << "Receive error for set notification settings: " << status; status.ignore(); - if (!td->auth_manager_->is_bot() && td->messages_manager_->get_input_notify_peer(scope_) != nullptr) { + if (!td->auth_manager_->is_bot()) { // trying to repair notification settings for this scope - td->create_handler(Promise<>())->send(scope_); + td->create_handler(Promise<>())->send(scope_); } } }; @@ -4168,14 +4258,61 @@ void MessagesManager::Message::parse(ParserT &parser) { } template -void store(const NotificationSettings ¬ification_settings, StorerT &storer) { +void store(const DialogNotificationSettings ¬ification_settings, StorerT &storer) { + bool is_muted = !notification_settings.use_default_mute_until && notification_settings.mute_until != 0 && + notification_settings.mute_until > G()->unix_time(); + bool has_sound = !notification_settings.use_default_sound && notification_settings.sound != "default"; + BEGIN_STORE_FLAGS(); + STORE_FLAG(is_muted); + STORE_FLAG(has_sound); + STORE_FLAG(notification_settings.show_preview); + STORE_FLAG(notification_settings.silent_send_message); + STORE_FLAG(notification_settings.is_synchronized); + STORE_FLAG(notification_settings.use_default_mute_until); + STORE_FLAG(notification_settings.use_default_sound); + STORE_FLAG(notification_settings.use_default_show_preview); + STORE_FLAG(notification_settings.is_use_default_fixed); + END_STORE_FLAGS(); + if (is_muted) { + store(notification_settings.mute_until, storer); + } + if (has_sound) { + store(notification_settings.sound, storer); + } +} + +template +void parse(DialogNotificationSettings ¬ification_settings, ParserT &parser) { + bool is_muted; + bool has_sound; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(is_muted); + PARSE_FLAG(has_sound); + PARSE_FLAG(notification_settings.show_preview); + PARSE_FLAG(notification_settings.silent_send_message); + PARSE_FLAG(notification_settings.is_synchronized); + PARSE_FLAG(notification_settings.use_default_mute_until); + PARSE_FLAG(notification_settings.use_default_sound); + PARSE_FLAG(notification_settings.use_default_show_preview); + PARSE_FLAG(notification_settings.is_use_default_fixed); + END_PARSE_FLAGS(); + if (is_muted) { + parse(notification_settings.mute_until, parser); + } + if (has_sound) { + parse(notification_settings.sound, parser); + } +} + +template +void store(const ScopeNotificationSettings ¬ification_settings, StorerT &storer) { bool is_muted = notification_settings.mute_until != 0 && notification_settings.mute_until > G()->unix_time(); bool has_sound = notification_settings.sound != "default"; BEGIN_STORE_FLAGS(); STORE_FLAG(is_muted); STORE_FLAG(has_sound); STORE_FLAG(notification_settings.show_preview); - STORE_FLAG(notification_settings.silent_send_message); + STORE_FLAG(false); STORE_FLAG(notification_settings.is_synchronized); END_STORE_FLAGS(); if (is_muted) { @@ -4187,14 +4324,15 @@ void store(const NotificationSettings ¬ification_settings, StorerT &storer) { } template -void parse(NotificationSettings ¬ification_settings, ParserT &parser) { +void parse(ScopeNotificationSettings ¬ification_settings, ParserT &parser) { bool is_muted; bool has_sound; + bool silent_send_message_ignored; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_muted); PARSE_FLAG(has_sound); PARSE_FLAG(notification_settings.show_preview); - PARSE_FLAG(notification_settings.silent_send_message); + PARSE_FLAG(silent_send_message_ignored); PARSE_FLAG(notification_settings.is_synchronized); END_PARSE_FLAGS(); if (is_muted) { @@ -4672,8 +4810,13 @@ void MessagesManager::on_dialog_unmute_timeout_callback(void *messages_manager_p } 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)); + if (1 <= dialog_id_int && dialog_id_int <= 2) { + send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_scope_unmute, + static_cast(dialog_id_int - 1)); + } else { + send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_dialog_unmute, + DialogId(dialog_id_int)); + } } void MessagesManager::on_pending_send_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) { @@ -6083,102 +6226,99 @@ void MessagesManager::drop_pending_updates() { } NotificationSettingsScope MessagesManager::get_notification_settings_scope( - tl_object_ptr &¬ify_peer_ptr) const { - switch (notify_peer_ptr->get_id()) { - case telegram_api::notifyPeer::ID: { - auto notify_peer = move_tl_object_as(notify_peer_ptr); - return DialogId(notify_peer->peer_).get(); - } - case telegram_api::notifyUsers::ID: - return NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS; - case telegram_api::notifyChats::ID: - return NOTIFICATION_SETTINGS_FOR_GROUP_CHATS; - case telegram_api::notifyAll::ID: - return NOTIFICATION_SETTINGS_FOR_ALL_CHATS; - default: - UNREACHABLE(); - return 0; - } -} - -NotificationSettingsScope MessagesManager::get_notification_settings_scope( - const tl_object_ptr &scope) const { - if (scope == nullptr) { - return NOTIFICATION_SETTINGS_FOR_ALL_CHATS; - } - int32 scope_id = scope->get_id(); - switch (scope_id) { - case td_api::notificationSettingsScopeChat::ID: - return static_cast(scope.get())->chat_id_; + const tl_object_ptr &scope) { + CHECK(scope != nullptr); + switch (scope->get_id()) { case td_api::notificationSettingsScopePrivateChats::ID: - return NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS; - case td_api::notificationSettingsScopeBasicGroupChats::ID: - return NOTIFICATION_SETTINGS_FOR_GROUP_CHATS; - case td_api::notificationSettingsScopeAllChats::ID: - return NOTIFICATION_SETTINGS_FOR_ALL_CHATS; + return NotificationSettingsScope::Private; + case td_api::notificationSettingsScopeGroupChats::ID: + return NotificationSettingsScope::Group; default: UNREACHABLE(); - return 0; + return NotificationSettingsScope::Private; } } string MessagesManager::get_notification_settings_scope_database_key(NotificationSettingsScope scope) { switch (scope) { - case NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS: + case NotificationSettingsScope::Private: return "nsfpc"; - case NOTIFICATION_SETTINGS_FOR_GROUP_CHATS: + case NotificationSettingsScope::Group: return "nsfgc"; - case NOTIFICATION_SETTINGS_FOR_ALL_CHATS: - return "nsfac"; default: UNREACHABLE(); return ""; } } -bool MessagesManager::update_notification_settings(NotificationSettingsScope scope, - NotificationSettings *current_settings, - const NotificationSettings &new_settings) { +bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id, + DialogNotificationSettings *current_settings, + const DialogNotificationSettings &new_settings) { bool need_update = current_settings->mute_until != new_settings.mute_until || current_settings->sound != new_settings.sound || current_settings->show_preview != new_settings.show_preview || - current_settings->is_synchronized != new_settings.is_synchronized; - bool is_changed = need_update || current_settings->silent_send_message != new_settings.silent_send_message; + current_settings->use_default_mute_until != new_settings.use_default_mute_until || + current_settings->use_default_sound != new_settings.use_default_sound || + current_settings->use_default_show_preview != new_settings.use_default_show_preview; + bool is_changed = need_update || current_settings->is_synchronized != new_settings.is_synchronized || + current_settings->silent_send_message != new_settings.silent_send_message || + current_settings->is_use_default_fixed != new_settings.is_use_default_fixed; if (is_changed) { - if (scope != NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS && scope != NOTIFICATION_SETTINGS_FOR_GROUP_CHATS && - scope != NOTIFICATION_SETTINGS_FOR_ALL_CHATS) { - DialogId dialog_id(scope); - CHECK(dialog_id.is_valid()); - Dialog *d = get_dialog(dialog_id); - CHECK(d != nullptr) << "Wrong " << dialog_id << " in update_notification_settings"; - update_dialog_unmute_timeout(d, 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()); + Dialog *d = get_dialog(dialog_id); + CHECK(d != nullptr) << "Wrong " << dialog_id << " in update_dialog_notification_settings"; + update_dialog_unmute_timeout(d, current_settings->use_default_mute_until, current_settings->mute_until, + new_settings.use_default_mute_until, new_settings.mute_until); + on_dialog_updated(dialog_id, "update_dialog_notification_settings"); + + LOG(INFO) << "Update notification settings in " << dialog_id << " from " << *current_settings << " to " + << new_settings; + *current_settings = new_settings; + + if (need_update) { + send_closure(G()->td(), &Td::send_update, + make_tl_object( + dialog_id.get(), get_chat_notification_settings_object(current_settings))); } + } + return is_changed; +} + +bool MessagesManager::update_scope_notification_settings(NotificationSettingsScope scope, + ScopeNotificationSettings *current_settings, + const ScopeNotificationSettings &new_settings) { + bool need_update = current_settings->mute_until != new_settings.mute_until || + current_settings->sound != new_settings.sound || + current_settings->show_preview != new_settings.show_preview; + bool is_changed = need_update || current_settings->is_synchronized != new_settings.is_synchronized; + if (is_changed) { + 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()); + + update_scope_unmute_timeout(scope, current_settings->mute_until, new_settings.mute_until); + LOG(INFO) << "Update notification settings in " << scope << " from " << *current_settings << " to " << new_settings; *current_settings = new_settings; if (need_update) { send_closure( G()->td(), &Td::send_update, - make_tl_object(get_notification_settings_scope_object(scope), - get_notification_settings_object(current_settings))); + make_tl_object( + get_notification_settings_scope_object(scope), get_scope_notification_settings_object(current_settings))); } } return is_changed; } -void MessagesManager::update_dialog_unmute_timeout(Dialog *d, int32 old_mute_until, int32 new_mute_until) { - if (old_mute_until == new_mute_until) { +void MessagesManager::update_dialog_unmute_timeout(Dialog *d, bool old_use_default, int32 old_mute_until, + bool new_use_default, int32 new_mute_until) { + if (old_use_default == new_use_default && old_mute_until == new_mute_until) { return; } CHECK(d != nullptr); auto now = G()->unix_time_cached(); - if (new_mute_until >= now && new_mute_until < now + 366 * 86400) { + if (!new_use_default && new_mute_until >= now && new_mute_until < now + 366 * 86400) { dialog_unmute_timeout_.set_timeout_in(d->dialog_id.get(), new_mute_until - now + 1); } else { dialog_unmute_timeout_.cancel_timeout(d->dialog_id.get()); @@ -6187,6 +6327,15 @@ void MessagesManager::update_dialog_unmute_timeout(Dialog *d, int32 old_mute_unt if (old_mute_until != -1 && is_unread_count_inited_ && d->order != DEFAULT_ORDER) { auto unread_count = d->server_unread_count + d->local_unread_count; if (unread_count != 0) { + if (old_use_default || new_use_default) { + auto scope_mute_until = get_scope_mute_until(d->dialog_id); + if (old_use_default) { + old_mute_until = scope_mute_until; + } + if (new_use_default) { + new_mute_until = scope_mute_until; + } + } if (old_mute_until != 0 && new_mute_until == 0) { unread_message_muted_count_ -= unread_count; send_update_unread_message_count(d->dialog_id, true, "on_dialog_unmute"); @@ -6199,10 +6348,51 @@ void MessagesManager::update_dialog_unmute_timeout(Dialog *d, int32 old_mute_unt } } +void MessagesManager::update_scope_unmute_timeout(NotificationSettingsScope scope, int32 old_mute_until, + int32 new_mute_until) { + LOG(INFO) << "Update " << scope << " unmute timeout from " << old_mute_until << " to " << 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(static_cast(scope) + 1, new_mute_until - now + 1); + } else { + dialog_unmute_timeout_.cancel_timeout(static_cast(scope) + 1); + } + + if (old_mute_until != -1 && is_unread_count_inited_) { + auto was_muted = old_mute_until != 0; + auto is_muted = new_mute_until != 0; + if (was_muted != is_muted) { + int32 delta = 0; + for (auto &dialog : dialogs_) { + Dialog *d = dialog.second.get(); + if (d->order != DEFAULT_ORDER && d->notification_settings.use_default_mute_until && + get_dialog_notification_setting_scope(d->dialog_id) == scope) { + delta += d->server_unread_count + d->local_unread_count; + } + } + if (delta != 0) { + if (was_muted) { + unread_message_muted_count_ -= delta; + } else { + unread_message_muted_count_ += delta; + } + send_update_unread_message_count(DialogId(), true, "update_scope_unmute_timeout"); + } + } + } +} + void MessagesManager::on_dialog_unmute(DialogId dialog_id) { auto d = get_dialog(dialog_id); CHECK(d != nullptr); + if (d->notification_settings.use_default_mute_until) { + return; + } if (d->notification_settings.mute_until == 0) { return; } @@ -6211,32 +6401,72 @@ void MessagesManager::on_dialog_unmute(DialogId dialog_id) { 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(d, -1, d->notification_settings.mute_until); + update_dialog_unmute_timeout(d, false, -1, false, d->notification_settings.mute_until); return; } LOG(INFO) << "Unmute " << dialog_id; - update_dialog_unmute_timeout(d, d->notification_settings.mute_until, 0); + update_dialog_unmute_timeout(d, false, d->notification_settings.mute_until, false, 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))); + make_tl_object( + dialog_id.get(), get_chat_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)); +void MessagesManager::on_scope_unmute(NotificationSettingsScope scope) { + auto notification_settings = get_scope_notification_settings(scope); + CHECK(notification_settings != nullptr); + + if (notification_settings->mute_until == 0) { + return; + } + + auto now = G()->unix_time(); + if (notification_settings->mute_until > now) { + LOG(ERROR) << "Failed to unmute " << scope << " in " << now << ", will be unmuted in " + << notification_settings->mute_until; + update_scope_unmute_timeout(scope, -1, notification_settings->mute_until); + return; + } + + LOG(INFO) << "Unmute " << scope; + update_scope_unmute_timeout(scope, notification_settings->mute_until, 0); + notification_settings->mute_until = 0; + send_closure(G()->td(), &Td::send_update, + make_tl_object( + get_notification_settings_scope_object(scope), + get_scope_notification_settings_object(notification_settings))); + string key = get_notification_settings_scope_database_key(scope); + G()->td_db()->get_binlog_pmc()->set(key, log_event_store(*notification_settings).as_slice().str()); +} + +void MessagesManager::on_update_dialog_notify_settings( + DialogId dialog_id, tl_object_ptr &&peer_notify_settings) { + LOG(INFO) << "Receive notification settings for " << dialog_id << ": " << to_string(peer_notify_settings); + + const DialogNotificationSettings notification_settings = + get_dialog_notification_settings(std::move(peer_notify_settings)); if (!notification_settings.is_synchronized) { return; } - NotificationSettings *current_settings = get_notification_settings(scope, true); + DialogNotificationSettings *current_settings = get_dialog_notification_settings(dialog_id, true); if (current_settings == nullptr) { return; } - update_notification_settings(scope, current_settings, notification_settings); + update_dialog_notification_settings(dialog_id, current_settings, notification_settings); +} + +void MessagesManager::on_update_scope_notify_settings( + NotificationSettingsScope scope, tl_object_ptr &&peer_notify_settings) { + const ScopeNotificationSettings notification_settings = + get_scope_notification_settings(std::move(peer_notify_settings)); + if (!notification_settings.is_synchronized) { + return; + } + + update_scope_notification_settings(scope, get_scope_notification_settings(scope), notification_settings); } bool MessagesManager::get_dialog_report_spam_state(DialogId dialog_id, Promise &&promise) { @@ -8652,7 +8882,9 @@ void MessagesManager::recalc_unread_message_count() { int unread_count = d->server_unread_count + d->local_unread_count; if (d->order != DEFAULT_ORDER && unread_count > 0) { total_count += unread_count; - if (d->notification_settings.mute_until != 0) { + auto mute_until = d->notification_settings.use_default_mute_until ? get_scope_mute_until(dialog_id) + : d->notification_settings.mute_until; + if (mute_until != 0) { muted_count += unread_count; } else { LOG(DEBUG) << "Have " << unread_count << " messages in unmuted " << dialog_id; @@ -8690,7 +8922,9 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId int32 delta = new_unread_count - old_unread_count; if (delta != 0 && d->order != DEFAULT_ORDER && is_unread_count_inited_) { unread_message_total_count_ += delta; - if (d->notification_settings.mute_until != 0) { + auto mute_until = d->notification_settings.use_default_mute_until ? get_scope_mute_until(d->dialog_id) + : d->notification_settings.mute_until; + if (mute_until != 0) { unread_message_muted_count_ += delta; } send_update_unread_message_count(d->dialog_id, force_update, source); @@ -9225,23 +9459,24 @@ void MessagesManager::start_up() { } load_calls_db_state(); - vector scopes{NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS, - NOTIFICATION_SETTINGS_FOR_GROUP_CHATS, NOTIFICATION_SETTINGS_FOR_ALL_CHATS}; + vector scopes{NotificationSettingsScope::Private, NotificationSettingsScope::Group}; for (auto scope : scopes) { auto notification_settings_string = G()->td_db()->get_binlog_pmc()->get(get_notification_settings_scope_database_key(scope)); if (!notification_settings_string.empty()) { - NotificationSettings notification_settings; + ScopeNotificationSettings notification_settings; log_event_parse(notification_settings, notification_settings_string).ensure(); if (!notification_settings.is_synchronized) { continue; } - NotificationSettings *current_settings = get_notification_settings(scope, true); + auto current_settings = get_scope_notification_settings(scope); CHECK(current_settings != nullptr); - update_notification_settings(scope, current_settings, notification_settings); + current_settings->mute_until = -1; + update_scope_notification_settings(scope, current_settings, notification_settings); } } + G()->td_db()->get_binlog_pmc()->erase("nsfac"); /* FI LE *f = std::f open("error.txt", "r"); @@ -10586,7 +10821,7 @@ void MessagesManager::on_get_dialogs(vector> } bool is_new = d->last_new_message_id == MessageId(); - on_update_notify_settings(dialog_id.get(), std::move(dialog->notify_settings_)); + on_update_dialog_notify_settings(dialog_id, std::move(dialog->notify_settings_)); if (dialog->unread_count_ < 0) { LOG(ERROR) << "Receive " << dialog->unread_count_ << " as number of unread messages in " << dialog_id; @@ -12267,8 +12502,8 @@ DialogId MessagesManager::create_new_group_chat(const vector &user_ids, created_dialogs_.erase(it); // set default notification settings to newly created chat - on_update_notify_settings(dialog_id.get(), - make_tl_object(1, true, false, 0, "default")); + on_update_dialog_notify_settings(dialog_id, + make_tl_object(0, false, false, 0, "")); promise.set_value(Unit()); return dialog_id; @@ -12320,8 +12555,8 @@ DialogId MessagesManager::create_new_channel_chat(const string &title, bool is_m created_dialogs_.erase(it); // set default notification settings to newly created chat - on_update_notify_settings(dialog_id.get(), - make_tl_object(1, true, false, 0, "default")); + on_update_dialog_notify_settings(dialog_id, + make_tl_object(0, false, false, 0, "")); promise.set_value(Unit()); return dialog_id; @@ -12751,7 +12986,7 @@ tl_object_ptr MessagesManager::get_chat_object(const Dialog *d) { DialogDate(d->order, d->dialog_id) <= last_dialog_date_ ? d->order : 0, d->pinned_order != DEFAULT_ORDER, can_report_dialog(d->dialog_id), d->server_unread_count + d->local_unread_count, d->last_read_inbox_message_id.get(), d->last_read_outbox_message_id.get(), d->unread_mention_count, - get_notification_settings_object(&d->notification_settings), d->reply_markup_message_id.get(), + get_chat_notification_settings_object(&d->notification_settings), d->reply_markup_message_id.get(), get_draft_message_object(d->draft_message), d->client_data); } @@ -12768,71 +13003,76 @@ tl_object_ptr MessagesManager::get_chats_object(const vector MessagesManager::get_notification_settings_scope_object( NotificationSettingsScope scope) { switch (scope) { - case NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS: + case NotificationSettingsScope::Private: return make_tl_object(); - case NOTIFICATION_SETTINGS_FOR_GROUP_CHATS: - return make_tl_object(); - case NOTIFICATION_SETTINGS_FOR_ALL_CHATS: - return make_tl_object(); - default: - return make_tl_object(scope); - } -} - -tl_object_ptr MessagesManager::get_notification_settings_object( - const NotificationSettings *notification_settings) { - return make_tl_object(max(0, notification_settings->mute_until - G()->unix_time()), - notification_settings->sound, - notification_settings->show_preview); -} - -const NotificationSettings *MessagesManager::get_dialog_notification_settings(const Dialog *d, - DialogId dialog_id) const { - if (d != nullptr && - d->notification_settings.is_synchronized) { // TODO this is wrong check for initialized notification settings - return &d->notification_settings; - } - - const NotificationSettings *notification_settings = nullptr; - switch (dialog_id.get_type()) { - case DialogType::User: - case DialogType::SecretChat: - notification_settings = &users_notification_settings_; - break; - case DialogType::Chat: - notification_settings = &chats_notification_settings_; - break; - case DialogType::Channel: { - ChannelId channel_id = dialog_id.get_channel_id(); - auto channel_type = td_->contacts_manager_->get_channel_type(channel_id); - if (channel_type == ChannelType::Megagroup) { - return nullptr; - } - notification_settings = &chats_notification_settings_; - break; - } - case DialogType::None: + case NotificationSettingsScope::Group: + return make_tl_object(); default: UNREACHABLE(); return nullptr; } - if (notification_settings->is_synchronized) { - return notification_settings; - } - return &dialogs_notification_settings_; } -const NotificationSettings *MessagesManager::get_notification_settings(NotificationSettingsScope scope, - Promise &&promise) { - const NotificationSettings *notification_settings = get_notification_settings(scope, true); - if (notification_settings == nullptr) { - promise.set_error(Status::Error(3, "Chat not found")); - return nullptr; +tl_object_ptr MessagesManager::get_chat_notification_settings_object( + const DialogNotificationSettings *notification_settings) { + return make_tl_object( + notification_settings->use_default_mute_until, max(0, notification_settings->mute_until - G()->unix_time()), + notification_settings->use_default_sound, notification_settings->sound, + notification_settings->use_default_show_preview, notification_settings->show_preview); +} + +tl_object_ptr MessagesManager::get_scope_notification_settings_object( + const ScopeNotificationSettings *notification_settings) { + return make_tl_object(max(0, notification_settings->mute_until - G()->unix_time()), + notification_settings->sound, + notification_settings->show_preview); +} + +std::pair MessagesManager::get_dialog_mute_until(DialogId dialog_id, const Dialog *d) const { + if (d == nullptr || !d->notification_settings.is_synchronized) { + return {false, get_scope_mute_until(dialog_id)}; } - if (!notification_settings->is_synchronized && get_notification_settings(scope, false) != nullptr && - !td_->auth_manager_->is_bot()) { - td_->create_handler(std::move(promise))->send(scope); + return {true, d->notification_settings.use_default_mute_until ? get_scope_mute_until(dialog_id) + : d->notification_settings.mute_until}; +} + +NotificationSettingsScope MessagesManager::get_dialog_notification_setting_scope(DialogId dialog_id) { + switch (dialog_id.get_type()) { + case DialogType::User: + case DialogType::SecretChat: + return NotificationSettingsScope::Private; + case DialogType::Chat: + case DialogType::Channel: + return NotificationSettingsScope::Group; + case DialogType::None: + default: + UNREACHABLE(); + return NotificationSettingsScope::Private; + } +} + +int32 MessagesManager::get_scope_mute_until(DialogId dialog_id) const { + switch (dialog_id.get_type()) { + case DialogType::User: + case DialogType::SecretChat: + return users_notification_settings_.mute_until; + case DialogType::Chat: + case DialogType::Channel: + return chats_notification_settings_.mute_until; + case DialogType::None: + default: + UNREACHABLE(); + return 0; + } +} + +const ScopeNotificationSettings *MessagesManager::get_scope_notification_settings(NotificationSettingsScope scope, + Promise &&promise) { + const ScopeNotificationSettings *notification_settings = get_scope_notification_settings(scope); + CHECK(notification_settings != nullptr); + if (!notification_settings->is_synchronized && !td_->auth_manager_->is_bot()) { + td_->create_handler(std::move(promise))->send(scope); return nullptr; } @@ -12840,53 +13080,53 @@ const NotificationSettings *MessagesManager::get_notification_settings(Notificat return notification_settings; } -NotificationSettings *MessagesManager::get_notification_settings(NotificationSettingsScope scope, bool force) { +DialogNotificationSettings *MessagesManager::get_dialog_notification_settings(DialogId dialog_id, bool force) { + auto dialog = get_dialog_force(dialog_id); + if (dialog == nullptr) { + return nullptr; + } + if (!force && !have_input_peer(dialog_id, AccessRights::Read)) { + return nullptr; + } + return &dialog->notification_settings; +} + +ScopeNotificationSettings *MessagesManager::get_scope_notification_settings(NotificationSettingsScope scope) { switch (scope) { - case NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS: + case NotificationSettingsScope::Private: return &users_notification_settings_; - case NOTIFICATION_SETTINGS_FOR_GROUP_CHATS: + case NotificationSettingsScope::Group: return &chats_notification_settings_; - case NOTIFICATION_SETTINGS_FOR_ALL_CHATS: - return &dialogs_notification_settings_; - default: { - DialogId dialog_id(scope); - auto dialog = get_dialog_force(dialog_id); - if (dialog == nullptr) { - return nullptr; - } - if (!force && !have_input_peer(dialog_id, AccessRights::Read)) { - return nullptr; - } - return &dialog->notification_settings; - } + default: + UNREACHABLE(); + return nullptr; } } -tl_object_ptr MessagesManager::get_input_notify_peer( - NotificationSettingsScope scope) const { +tl_object_ptr MessagesManager::get_input_notify_peer(DialogId dialog_id) const { + if (get_dialog(dialog_id) == nullptr) { + return nullptr; + } + auto input_peer = get_input_peer(dialog_id, AccessRights::Read); + if (input_peer == nullptr) { + return nullptr; + } + return make_tl_object(std::move(input_peer)); +} + +tl_object_ptr MessagesManager::get_input_notify_peer(NotificationSettingsScope scope) { switch (scope) { - case NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS: + case NotificationSettingsScope::Private: return make_tl_object(); - case NOTIFICATION_SETTINGS_FOR_GROUP_CHATS: + case NotificationSettingsScope::Group: return make_tl_object(); - case NOTIFICATION_SETTINGS_FOR_ALL_CHATS: - return make_tl_object(); - default: { - DialogId dialog_id(scope); - if (get_dialog(dialog_id) == nullptr) { - return nullptr; - } - auto input_peer = get_input_peer(dialog_id, AccessRights::Read); - if (input_peer == nullptr) { - return nullptr; - } - return make_tl_object(std::move(input_peer)); - } + default: + return nullptr; } } -Status MessagesManager::set_notification_settings(NotificationSettingsScope scope, - tl_object_ptr &¬ification_settings) { +Status MessagesManager::set_dialog_notification_settings( + DialogId dialog_id, tl_object_ptr &¬ification_settings) { if (notification_settings == nullptr) { return Status::Error(400, "New notification settings must not be empty"); } @@ -12894,7 +13134,7 @@ Status MessagesManager::set_notification_settings(NotificationSettingsScope scop return Status::Error(400, "Notification settings sound must be encoded in UTF-8"); } - auto current_settings = get_notification_settings(scope, false); + auto current_settings = get_dialog_notification_settings(dialog_id, false); if (current_settings == nullptr) { return Status::Error(6, "Wrong chat identifier specified"); } @@ -12904,6 +13144,37 @@ Status MessagesManager::set_notification_settings(NotificationSettingsScope scop notification_settings->mute_for_ = std::numeric_limits::max() - current_time; } + int32 mute_until; + if (notification_settings->use_default_mute_for_ || notification_settings->mute_for_ <= 0) { + mute_until = 0; + } else { + mute_until = notification_settings->mute_for_ + current_time; + } + + DialogNotificationSettings new_settings( + notification_settings->use_default_mute_for_, mute_until, notification_settings->use_default_sound_, + std::move(notification_settings->sound_), notification_settings->use_default_show_preview_, + notification_settings->show_preview_, current_settings->silent_send_message); + if (update_dialog_notification_settings(dialog_id, current_settings, new_settings)) { + td_->create_handler()->send(dialog_id, new_settings); + } + return Status::OK(); +} + +Status MessagesManager::set_scope_notification_settings( + NotificationSettingsScope scope, tl_object_ptr &¬ification_settings) { + if (notification_settings == nullptr) { + return Status::Error(400, "New notification settings must not be empty"); + } + if (!clean_input_string(notification_settings->sound_)) { + return Status::Error(400, "Notification settings sound must be encoded in UTF-8"); + } + + int32 current_time = G()->unix_time(); + if (notification_settings->mute_for_ > std::numeric_limits::max() - current_time) { + notification_settings->mute_for_ = std::numeric_limits::max() - current_time; + } + int32 mute_until; if (notification_settings->mute_for_ <= 0) { mute_until = 0; @@ -12911,35 +13182,29 @@ Status MessagesManager::set_notification_settings(NotificationSettingsScope scop mute_until = notification_settings->mute_for_ + current_time; } - NotificationSettings new_settings(mute_until, std::move(notification_settings->sound_), - notification_settings->show_preview_, current_settings->silent_send_message); + ScopeNotificationSettings new_settings(mute_until, std::move(notification_settings->sound_), + notification_settings->show_preview_); - if (update_notification_settings(scope, current_settings, new_settings)) { - td_->create_handler()->send(scope, new_settings); + if (update_scope_notification_settings(scope, get_scope_notification_settings(scope), new_settings)) { + td_->create_handler()->send(scope, new_settings); } return Status::OK(); } void MessagesManager::reset_all_notification_settings() { - NotificationSettings new_settings(0, "default", true, false); - NotificationSettings new_megagroup_settings(std::numeric_limits::max(), "default", true, false); + DialogNotificationSettings new_dialog_settings; + ScopeNotificationSettings new_scope_settings; + new_dialog_settings.is_synchronized = true; + new_scope_settings.is_synchronized = true; - update_notification_settings(NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS, &users_notification_settings_, new_settings); - update_notification_settings(NOTIFICATION_SETTINGS_FOR_GROUP_CHATS, &chats_notification_settings_, new_settings); - update_notification_settings(NOTIFICATION_SETTINGS_FOR_ALL_CHATS, &dialogs_notification_settings_, new_settings); + update_scope_notification_settings(NotificationSettingsScope::Private, &users_notification_settings_, + new_scope_settings); + update_scope_notification_settings(NotificationSettingsScope::Group, &chats_notification_settings_, + new_scope_settings); for (auto &dialog : dialogs_) { Dialog *d = dialog.second.get(); - auto dialog_id = d->dialog_id; - bool is_megagroup = dialog_id.get_type() == DialogType::Channel && - td_->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) == ChannelType::Megagroup; - - if (is_megagroup) { - update_notification_settings(NotificationSettingsScope(dialog_id.get()), &d->notification_settings, - new_megagroup_settings); - } else { - update_notification_settings(NotificationSettingsScope(dialog_id.get()), &d->notification_settings, new_settings); - } + update_dialog_notification_settings(d->dialog_id, &d->notification_settings, new_dialog_settings); } td_->create_handler()->send(); } @@ -14843,7 +15108,7 @@ MessagesManager::Message *MessagesManager::get_message_to_send(Dialog *d, Messag if (td_->auth_manager_->is_bot()) { m->disable_notification = disable_notification; } else { - auto notification_settings = get_notification_settings(NotificationSettingsScope(dialog_id.get()), true); + auto notification_settings = get_dialog_notification_settings(dialog_id, true); CHECK(notification_settings != nullptr); m->disable_notification = notification_settings->silent_send_message; } @@ -18365,14 +18630,11 @@ void MessagesManager::send_update_new_message(Dialog *d, const Message *m, bool settings_dialog = get_dialog_force(settings_dialog_id); } - auto notification_settings = get_dialog_notification_settings(settings_dialog, settings_dialog_id); - if (notification_settings == nullptr || // unknown megagroup without mention - notification_settings->mute_until > G()->unix_time()) { + int32 mute_until; + std::tie(have_settings, mute_until) = get_dialog_mute_until(settings_dialog_id, settings_dialog); + if (mute_until > G()->unix_time()) { disable_notification = true; } - if (settings_dialog == nullptr || !settings_dialog->notification_settings.is_synchronized) { - have_settings = false; - } } if (!force && (!have_settings || !d->pending_update_new_messages.empty())) { @@ -20564,18 +20826,31 @@ MessagesManager::Message *MessagesManager::on_get_message_from_database(DialogId return result; } -NotificationSettings MessagesManager::get_notification_settings( - tl_object_ptr &¬ification_settings) { - int32 constructor_id = notification_settings->get_id(); - if (constructor_id == telegram_api::peerNotifySettingsEmpty::ID) { - LOG(ERROR) << "Empty notify settings received"; - return {}; - } - CHECK(constructor_id == telegram_api::peerNotifySettings::ID); - auto settings = static_cast(notification_settings.get()); - auto mute_until = (settings->mute_until_ <= G()->unix_time() ? 0 : settings->mute_until_); - return {mute_until, settings->sound_, (settings->flags_ & telegram_api::peerNotifySettings::SHOW_PREVIEWS_MASK) != 0, - (settings->flags_ & telegram_api::peerNotifySettings::SILENT_MASK) != 0}; +DialogNotificationSettings MessagesManager::get_dialog_notification_settings( + tl_object_ptr &&settings) { + bool use_default_mute_until = (settings->flags_ & telegram_api::peerNotifySettings::MUTE_UNTIL_MASK) == 0; + bool use_default_sound = (settings->flags_ & telegram_api::peerNotifySettings::SOUND_MASK) == 0; + bool use_default_show_preview = (settings->flags_ & telegram_api::peerNotifySettings::SHOW_PREVIEWS_MASK) == 0; + auto mute_until = use_default_mute_until || settings->mute_until_ <= G()->unix_time() ? 0 : settings->mute_until_; + bool silent_send_message = + (settings->flags_ & telegram_api::peerNotifySettings::SILENT_MASK) == 0 ? false : settings->silent_; + return {use_default_mute_until, mute_until, + use_default_sound, std::move(settings->sound_), + use_default_show_preview, settings->show_previews_, + silent_send_message}; +} + +ScopeNotificationSettings MessagesManager::get_scope_notification_settings( + tl_object_ptr &&settings) { + auto mute_until = (settings->flags_ & telegram_api::peerNotifySettings::MUTE_UNTIL_MASK) == 0 || + settings->mute_until_ <= G()->unix_time() + ? 0 + : settings->mute_until_; + auto sound = + (settings->flags_ & telegram_api::peerNotifySettings::SOUND_MASK) == 0 ? "default" : std::move(settings->sound_); + auto show_preview = + (settings->flags_ & telegram_api::peerNotifySettings::SHOW_PREVIEWS_MASK) == 0 ? false : settings->show_previews_; + return {mute_until, std::move(sound), show_preview}; } unique_ptr MessagesManager::get_secret_message_document( @@ -23236,9 +23511,6 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr &&d, d->last_read_outbox_message_id = MessageId::max(); d->is_last_read_outbox_message_id_inited = true; } - if (!d->notification_settings.is_synchronized && channel_type == ChannelType::Megagroup) { - d->notification_settings.mute_until = std::numeric_limits::max(); - } auto pts = load_channel_pts(dialog_id); if (pts > 0) { @@ -23316,10 +23588,29 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab CHECK(d != nullptr); auto dialog_id = d->dialog_id; - if (d->notification_settings.mute_until <= G()->unix_time()) { + if (d->notification_settings.is_synchronized && !d->notification_settings.is_use_default_fixed && + have_input_peer(dialog_id, AccessRights::Read)) { + LOG(INFO) << "Reget notification settings of " << dialog_id; + if (d->dialog_id.get_type() == DialogType::SecretChat) { + if (d->notification_settings.mute_until == 0 && users_notification_settings_.mute_until == 0) { + d->notification_settings.use_default_mute_until = true; + } + if (d->notification_settings.sound == "default" && users_notification_settings_.sound == "default") { + d->notification_settings.use_default_sound = true; + } + if (d->notification_settings.show_preview && users_notification_settings_.show_preview) { + d->notification_settings.use_default_show_preview = true; + } + d->notification_settings.is_use_default_fixed = true; + on_dialog_updated(d->dialog_id, "reget notification settings"); + } else { + td_->create_handler(Promise())->send(dialog_id); + } + } + if (d->notification_settings.use_default_mute_until || d->notification_settings.mute_until <= G()->unix_time()) { d->notification_settings.mute_until = 0; } else { - update_dialog_unmute_timeout(d, -1, d->notification_settings.mute_until); + update_dialog_unmute_timeout(d, false, -1, false, d->notification_settings.mute_until); } auto pending_it = pending_add_dialog_last_database_message_dependent_dialogs_.find(dialog_id); @@ -23686,7 +23977,9 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen } unread_message_total_count_ += unread_count; - if (d->notification_settings.mute_until != 0) { + auto mute_until = d->notification_settings.use_default_mute_until ? get_scope_mute_until(d->dialog_id) + : d->notification_settings.mute_until; + if (mute_until != 0) { unread_message_muted_count_ += unread_count; } send_update_unread_message_count(d->dialog_id, true, source); @@ -23833,13 +24126,10 @@ void MessagesManager::load_notification_settings() { return; } if (!users_notification_settings_.is_synchronized) { - td_->create_handler(Promise<>())->send(NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS); + td_->create_handler(Promise<>())->send(NotificationSettingsScope::Private); } if (!chats_notification_settings_.is_synchronized) { - td_->create_handler(Promise<>())->send(NOTIFICATION_SETTINGS_FOR_GROUP_CHATS); - } - if (!dialogs_notification_settings_.is_synchronized) { - td_->create_handler(Promise<>())->send(NOTIFICATION_SETTINGS_FOR_ALL_CHATS); + td_->create_handler(Promise<>())->send(NotificationSettingsScope::Group); } } @@ -24315,6 +24605,9 @@ void MessagesManager::after_get_channel_difference(DialogId dialog_id, bool succ on_get_dialogs(std::move(res.dialogs), res.total_count, std::move(res.messages), std::move(res.promise)); } + // to repair unread message counts + td_->contacts_manager_->get_channel_full(dialog_id.get_channel_id(), Auto()); + // TODO resend some messages } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 705cae38..23b69c93 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -678,37 +678,73 @@ class DraftMessage { InputMessageText input_message_text; }; -using NotificationSettingsScope = int64; -constexpr NotificationSettingsScope NOTIFICATION_SETTINGS_FOR_PRIVATE_CHATS = - std::numeric_limits::min(); -constexpr NotificationSettingsScope NOTIFICATION_SETTINGS_FOR_GROUP_CHATS = - std::numeric_limits::min() + 1; -constexpr NotificationSettingsScope NOTIFICATION_SETTINGS_FOR_ALL_CHATS = - std::numeric_limits::min() + 2; - -class NotificationSettings { +class DialogNotificationSettings { public: int32 mute_until = 0; string sound = "default"; bool show_preview = true; bool silent_send_message = false; + bool use_default_mute_until = true; + bool use_default_sound = true; + bool use_default_show_preview = true; + bool is_use_default_fixed = true; bool is_synchronized = false; - NotificationSettings() = default; + DialogNotificationSettings() = default; - NotificationSettings(int32 mute_until, string sound, bool show_preview, bool silent_send_message) + DialogNotificationSettings(bool use_default_mute_until, int32 mute_until, bool use_default_sound, string sound, + bool use_default_show_preview, bool show_preview, bool silent_send_message) : mute_until(mute_until) , sound(std::move(sound)) , show_preview(show_preview) , silent_send_message(silent_send_message) + , use_default_mute_until(use_default_mute_until) + , use_default_sound(use_default_sound) + , use_default_show_preview(use_default_show_preview) , is_synchronized(true) { } }; -inline StringBuilder &operator<<(StringBuilder &string_builder, NotificationSettings notification_settings) { +enum class NotificationSettingsScope { Private, Group }; + +class ScopeNotificationSettings { + public: + int32 mute_until = 0; + string sound = "default"; + bool show_preview = true; + bool is_synchronized = false; + + ScopeNotificationSettings() = default; + + ScopeNotificationSettings(int32 mute_until, string sound, bool show_preview) + : mute_until(mute_until), sound(std::move(sound)), show_preview(show_preview), is_synchronized(true) { + } +}; + +inline StringBuilder &operator<<(StringBuilder &string_builder, DialogNotificationSettings 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 << "]"; + << ", " << notification_settings.use_default_mute_until << ", " + << notification_settings.use_default_sound << ", " + << notification_settings.use_default_show_preview << ", " + << notification_settings.is_synchronized << "]"; +} + +inline StringBuilder &operator<<(StringBuilder &string_builder, NotificationSettingsScope scope) { + switch (scope) { + case NotificationSettingsScope::Private: + return string_builder << "notification settings for private chats"; + case NotificationSettingsScope::Group: + return string_builder << "notification settings for group chats"; + default: + UNREACHABLE(); + return string_builder; + } +} + +inline StringBuilder &operator<<(StringBuilder &string_builder, ScopeNotificationSettings notification_settings) { + return string_builder << "[" << notification_settings.mute_until << ", " << notification_settings.sound << ", " + << notification_settings.show_preview << ", " << notification_settings.is_synchronized << "]"; } inline constexpr size_t search_messages_filter_size() { @@ -1214,13 +1250,23 @@ class MessagesManager : public Actor { static tl_object_ptr get_notification_settings_scope_object( NotificationSettingsScope scope); - static tl_object_ptr get_notification_settings_object( - const NotificationSettings *notification_settings); + static tl_object_ptr get_chat_notification_settings_object( + const DialogNotificationSettings *notification_settings); - const NotificationSettings *get_notification_settings(NotificationSettingsScope scope, Promise &&promise); + static tl_object_ptr get_scope_notification_settings_object( + const ScopeNotificationSettings *notification_settings); - Status set_notification_settings(NotificationSettingsScope scope, - tl_object_ptr &¬ification_settings) + const DialogNotificationSettings *get_dialog_notification_settings(DialogId dialog_id, Promise &&promise); + + const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope, + Promise &&promise); + + Status set_dialog_notification_settings(DialogId dialog_id, + tl_object_ptr &¬ification_settings) + TD_WARN_UNUSED_RESULT; + + Status set_scope_notification_settings(NotificationSettingsScope scope, + tl_object_ptr &¬ification_settings) TD_WARN_UNUSED_RESULT; void reset_all_notification_settings(); @@ -1290,16 +1336,18 @@ class MessagesManager : public Actor { static SearchMessagesFilter get_search_messages_filter(const tl_object_ptr &filter); - tl_object_ptr get_input_notify_peer(NotificationSettingsScope scope) const; + tl_object_ptr get_input_notify_peer(DialogId dialogId) const; - NotificationSettingsScope get_notification_settings_scope( - tl_object_ptr &¬ify_peer_ptr) const; + static tl_object_ptr get_input_notify_peer(NotificationSettingsScope scope); - NotificationSettingsScope get_notification_settings_scope( - const tl_object_ptr &scope) const; + static NotificationSettingsScope get_notification_settings_scope( + const tl_object_ptr &scope); - void on_update_notify_settings(NotificationSettingsScope scope, - tl_object_ptr &&peer_notify_settings); + void on_update_dialog_notify_settings(DialogId dialog_id, + tl_object_ptr &&peer_notify_settings); + + void on_update_scope_notify_settings(NotificationSettingsScope scope, + tl_object_ptr &&peer_notify_settings); bool get_dialog_report_spam_state(DialogId dialog_id, Promise &&promise); @@ -1525,7 +1573,7 @@ class MessagesManager : public Actor { MessageId last_read_inbox_message_id; MessageId last_read_outbox_message_id; MessageId reply_markup_message_id; - NotificationSettings notification_settings; + DialogNotificationSettings notification_settings; unique_ptr draft_message; uint64 save_draft_message_logevent_id = 0; uint64 save_draft_message_logevent_id_generation = 0; @@ -2188,13 +2236,21 @@ class MessagesManager : public Actor { static string get_notification_settings_scope_database_key(NotificationSettingsScope scope); - bool update_notification_settings(NotificationSettingsScope scope, NotificationSettings *current_settings, - const NotificationSettings &new_settings); + bool update_dialog_notification_settings(DialogId dialog_id, DialogNotificationSettings *current_settings, + const DialogNotificationSettings &new_settings); - void update_dialog_unmute_timeout(Dialog *d, int32 old_mute_until, int32 new_mute_until); + bool update_scope_notification_settings(NotificationSettingsScope scope, ScopeNotificationSettings *current_settings, + const ScopeNotificationSettings &new_settings); + + void update_dialog_unmute_timeout(Dialog *d, bool old_use_default, int32 old_mute_until, bool new_use_default, + int32 new_mute_until); + + void update_scope_unmute_timeout(NotificationSettingsScope scope, int32 old_mute_until, int32 new_mute_until); void on_dialog_unmute(DialogId dialog_id); + void on_scope_unmute(NotificationSettingsScope scope); + void on_send_dialog_action_timeout(DialogId dialog_id); void on_active_dialog_action_timeout(DialogId dialog_id); @@ -2273,12 +2329,21 @@ class MessagesManager : public Actor { void on_get_dialog_message_by_date_from_database(DialogId dialog_id, int32 date, int64 random_id, Result result, Promise promise); - static NotificationSettings get_notification_settings( - tl_object_ptr &¬ification_settings); + static DialogNotificationSettings get_dialog_notification_settings( + tl_object_ptr &&settings); - const NotificationSettings *get_dialog_notification_settings(const Dialog *d, DialogId dialog_id) const; + static ScopeNotificationSettings get_scope_notification_settings( + tl_object_ptr &&settings); - NotificationSettings *get_notification_settings(NotificationSettingsScope scope, bool force); + std::pair get_dialog_mute_until(DialogId dialog_id, const Dialog *d) const; + + static NotificationSettingsScope get_dialog_notification_setting_scope(DialogId dialog_id); + + int32 get_scope_mute_until(DialogId dialog_id) const; + + DialogNotificationSettings *get_dialog_notification_settings(DialogId dialog_id, bool force); + + ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope); static unique_ptr get_draft_message(ContactsManager *contacts_manager, tl_object_ptr &&draft_message_ptr); @@ -2690,9 +2755,8 @@ class MessagesManager : public Actor { std::unordered_map, DialogIdHash> active_dialog_actions_; - NotificationSettings users_notification_settings_; - NotificationSettings chats_notification_settings_; - NotificationSettings dialogs_notification_settings_; + ScopeNotificationSettings users_notification_settings_; + ScopeNotificationSettings chats_notification_settings_; bool have_postponed_unread_message_count_update_ = false; bool is_unread_count_inited_ = false; diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index 27c648c7..5ac818c3 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -19,8 +19,6 @@ #include -#include "td/utils/base64.h" - namespace td { GetSecureValue::GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 521d14c2..3653ee57 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2690,22 +2690,22 @@ class GetUserProfilePhotosRequest : public RequestActor<> { } }; -class GetNotificationSettingsRequest : public RequestActor<> { +class GetScopeNotificationSettingsRequest : public RequestActor<> { NotificationSettingsScope scope_; - const NotificationSettings *notification_settings_ = nullptr; + const ScopeNotificationSettings *notification_settings_ = nullptr; void do_run(Promise &&promise) override { - notification_settings_ = td->messages_manager_->get_notification_settings(scope_, std::move(promise)); + notification_settings_ = td->messages_manager_->get_scope_notification_settings(scope_, std::move(promise)); } void do_send_result() override { CHECK(notification_settings_ != nullptr); - send_result(td->messages_manager_->get_notification_settings_object(notification_settings_)); + send_result(td->messages_manager_->get_scope_notification_settings_object(notification_settings_)); } public: - GetNotificationSettingsRequest(ActorShared td, uint64 request_id, NotificationSettingsScope scope) + GetScopeNotificationSettingsRequest(ActorShared td, uint64 request_id, NotificationSettingsScope scope) : RequestActor(std::move(td), request_id), scope_(scope) { } }; @@ -3878,6 +3878,7 @@ void Td::request(uint64 id, tl_object_ptr function) { return send_error_raw(id, 400, "Request is empty"); } + VLOG(td_requests) << "Receive request " << id << ": " << to_string(function); switch (state_) { case State::WaitParameters: { switch (function->get_id()) { @@ -3934,7 +3935,6 @@ void Td::request(uint64 id, tl_object_ptr function) { break; } - VLOG(td_requests) << "Receive request " << id << ": " << to_string(function); downcast_call(*function, [this, id](auto &request) { this->on_request(id, request); }); } @@ -6534,10 +6534,13 @@ void Td::on_request(uint64 id, td_api::removeSavedAnimation &request) { CREATE_REQUEST(RemoveSavedAnimationRequest, std::move(request.animation_)); } -void Td::on_request(uint64 id, const td_api::getNotificationSettings &request) { +void Td::on_request(uint64 id, const td_api::getScopeNotificationSettings &request) { CHECK_AUTH(); CHECK_IS_USER(); - CREATE_REQUEST(GetNotificationSettingsRequest, messages_manager_->get_notification_settings_scope(request.scope_)); + if (request.scope_ == nullptr) { + return send_error_raw(id, 400, "Scope must not be empty"); + } + CREATE_REQUEST(GetScopeNotificationSettingsRequest, MessagesManager::get_notification_settings_scope(request.scope_)); } void Td::on_request(uint64 id, const td_api::getChatReportSpamState &request) { @@ -6558,12 +6561,21 @@ void Td::on_request(uint64 id, td_api::reportChat &request) { CREATE_REQUEST(ReportChatRequest, request.chat_id_, std::move(request.reason_), request.message_ids_); } -void Td::on_request(uint64 id, td_api::setNotificationSettings &request) { +void Td::on_request(uint64 id, td_api::setChatNotificationSettings &request) { CHECK_AUTH(); CHECK_IS_USER(); - CLEAN_INPUT_STRING(request.notification_settings_->sound_); - answer_ok_query(id, messages_manager_->set_notification_settings( - messages_manager_->get_notification_settings_scope(request.scope_), + answer_ok_query(id, messages_manager_->set_dialog_notification_settings(DialogId(request.chat_id_), + std::move(request.notification_settings_))); +} + +void Td::on_request(uint64 id, td_api::setScopeNotificationSettings &request) { + CHECK_AUTH(); + CHECK_IS_USER(); + if (request.scope_ == nullptr) { + return send_error_raw(id, 400, "Scope must not be empty"); + } + answer_ok_query(id, messages_manager_->set_scope_notification_settings( + MessagesManager::get_notification_settings_scope(request.scope_), std::move(request.notification_settings_))); } diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 30275153..8ece32d0 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -707,9 +707,11 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::removeFavoriteSticker &request); - void on_request(uint64 id, const td_api::getNotificationSettings &request); + void on_request(uint64 id, const td_api::getScopeNotificationSettings &request); - void on_request(uint64 id, td_api::setNotificationSettings &request); + void on_request(uint64 id, td_api::setChatNotificationSettings &request); + + void on_request(uint64 id, td_api::setScopeNotificationSettings &request); void on_request(uint64 id, const td_api::resetAllNotificationSettings &request); diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index aaa8f0db..2a0e7b13 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1479,9 +1479,25 @@ void UpdatesManager::on_update(tl_object_ptr update, bool /*force_apply*/) { CHECK(update != nullptr); - td_->messages_manager_->on_update_notify_settings( - td_->messages_manager_->get_notification_settings_scope(std::move(update->peer_)), - std::move(update->notify_settings_)); + switch (update->peer_->get_id()) { + case telegram_api::notifyPeer::ID: { + DialogId dialog_id(static_cast(update->peer_.get())->peer_); + if (dialog_id.is_valid()) { + td_->messages_manager_->on_update_dialog_notify_settings(dialog_id, std::move(update->notify_settings_)); + } else { + LOG(ERROR) << "Receive wrong " << to_string(update); + } + break; + } + case telegram_api::notifyUsers::ID: + return td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Private, + std::move(update->notify_settings_)); + case telegram_api::notifyChats::ID: + return td_->messages_manager_->on_update_scope_notify_settings(NotificationSettingsScope::Group, + std::move(update->notify_settings_)); + default: + UNREACHABLE(); + } } void UpdatesManager::on_update(tl_object_ptr update, bool force_apply) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 48e5c03e..abaa9376 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -773,15 +773,10 @@ class CliClient final : public Actor { } tl_object_ptr get_notification_settings_scope(Slice scope) const { - if (scope == "users" || scope == "privateChats") { - return make_tl_object(); - } else if (scope == "chats" || scope == "groups" || scope == "groupChats") { - return make_tl_object(); - } else if (scope == "all" || scope == "dialogs") { - return make_tl_object(); - } else { - return make_tl_object(as_chat_id(scope)); + if (scope == "chats" || scope == "groups" || scope == "channels" || as_bool(scope.str())) { + return make_tl_object(); } + return make_tl_object(); } static tl_object_ptr get_user_privacy_setting(MutableSlice setting) { @@ -2878,9 +2873,26 @@ class CliClient final : public Actor { send_request(make_tl_object(as_chat_id(chat_id))); } else if (op == "dpp") { send_request(make_tl_object(to_integer(args))); - } else if (op == "gns") { - send_request(make_tl_object(get_notification_settings_scope(args))); - } else if (op == "sns") { + } else if (op == "gsns") { + send_request(make_tl_object(get_notification_settings_scope(args))); + } else if (op == "scns") { + string chat_id; + string settings; + + std::tie(chat_id, settings) = split(args); + + string mute_for; + string sound; + string show_previews; + + std::tie(mute_for, settings) = split(settings, ','); + std::tie(sound, show_previews) = split(settings, ','); + + send_request(make_tl_object( + as_chat_id(chat_id), + make_tl_object(mute_for.empty(), to_integer(mute_for), sound.empty(), + sound, show_previews.empty(), as_bool(show_previews)))); + } else if (op == "ssns") { string scope; string settings; @@ -2893,9 +2905,9 @@ class CliClient final : public Actor { std::tie(mute_for, settings) = split(settings, ','); std::tie(sound, show_previews) = split(settings, ','); - send_request(make_tl_object( - get_notification_settings_scope(scope), - make_tl_object(to_integer(mute_for), sound, as_bool(show_previews)))); + send_request(make_tl_object( + get_notification_settings_scope(scope), make_tl_object( + to_integer(mute_for), sound, as_bool(show_previews)))); } else if (op == "rans") { send_request(make_tl_object()); } else if (op == "gcrss") {