From 178d6414dd710f7ca003965f4493c62493dee9a7 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 14 Apr 2022 14:31:18 +0300 Subject: [PATCH] Add td_api::removeSavedNotificationSound. --- td/generate/scheme/td_api.tl | 3 + td/telegram/Global.h | 9 ++ td/telegram/NotificationSettingsManager.cpp | 125 +++++++++++++++++++- td/telegram/NotificationSettingsManager.h | 7 ++ td/telegram/Td.cpp | 20 ++++ td/telegram/Td.h | 2 + td/telegram/cli.cpp | 8 +- 7 files changed, 172 insertions(+), 2 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b59efcf76..e5d5526fa 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -5184,6 +5184,9 @@ getSavedNotificationSound notification_sound_id:int64 = NotificationSounds; //@description Returns list of saved notification sounds. If a sound isn't in the list, then default sound needs to be used getSavedNotificationSounds = NotificationSounds; +//@description Removes a notification sound from the list of saved notification sounds @notification_sound_id Identifier of the notification sound +removeSavedNotificationSound notification_sound_id:int64 = Ok; + //@description Returns list of chats with non-default notification settings //@scope If specified, only chats from the scope will be returned; pass null to return chats from all scopes diff --git a/td/telegram/Global.h b/td/telegram/Global.h index 8162567aa..a148a7a9b 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -48,6 +48,7 @@ class MessagesManager; class MtprotoHeader; class NetQueryDispatcher; class NotificationManager; +class NotificationSettingsManager; class OptionManager; class PasswordManager; class SecretChatsManager; @@ -270,6 +271,13 @@ class Global final : public ActorContext { notification_manager_ = notification_manager; } + ActorId notification_settings_manager() const { + return notification_settings_manager_; + } + void set_notification_settings_manager(ActorId notification_settings_manager) { + notification_settings_manager_ = notification_settings_manager; + } + ActorId option_manager() const { return option_manager_; } @@ -457,6 +465,7 @@ class Global final : public ActorContext { ActorId link_manager_; ActorId messages_manager_; ActorId notification_manager_; + ActorId notification_settings_manager_; ActorId option_manager_; ActorId password_manager_; ActorId secret_chats_manager_; diff --git a/td/telegram/NotificationSettingsManager.cpp b/td/telegram/NotificationSettingsManager.cpp index 69f74a725..e6a942ef0 100644 --- a/td/telegram/NotificationSettingsManager.cpp +++ b/td/telegram/NotificationSettingsManager.cpp @@ -10,6 +10,7 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DocumentsManager.h" +#include "td/telegram/FileReferenceManager.h" #include "td/telegram/files/FileManager.h" #include "td/telegram/Global.h" #include "td/telegram/logevent/LogEvent.h" @@ -34,6 +35,65 @@ namespace td { +class SaveRingtoneQuery final : public Td::ResultHandler { + FileId file_id_; + string file_reference_; + bool unsave_ = false; + + Promise> promise_; + + public: + explicit SaveRingtoneQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(FileId file_id, tl_object_ptr &&input_document, bool unsave) { + CHECK(input_document != nullptr); + CHECK(file_id.is_valid()); + file_id_ = file_id; + file_reference_ = input_document->file_reference_.as_slice().str(); + unsave_ = unsave; + + send_query(G()->net_query_creator().create(telegram_api::account_saveRingtone(std::move(input_document), unsave), + {{"ringtone"}})); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto result = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for SaveRingtoneQuery: " << to_string(result); + promise_.set_value(std::move(result)); + } + + void on_error(Status status) final { + if (!td_->auth_manager_->is_bot() && FileReferenceManager::is_file_reference_error(status)) { + VLOG(file_references) << "Receive " << status << " for " << file_id_; + td_->file_manager_->delete_file_reference(file_id_, file_reference_); + td_->file_reference_manager_->repair_file_reference( + file_id_, PromiseCreator::lambda([ringtone_id = file_id_, unsave = unsave_, + promise = std::move(promise_)](Result result) mutable { + if (result.is_error()) { + return promise.set_error(Status::Error(400, "Failed to find the ringtone")); + } + + send_closure(G()->notification_settings_manager(), &NotificationSettingsManager::send_save_ringtone_query, + ringtone_id, unsave, std::move(promise)); + })); + return; + } + + if (!G()->is_expected_error(status)) { + LOG(ERROR) << "Receive error for SaveRingtoneQuery: " << status; + } + td_->notification_settings_manager_->reload_saved_ringtones(Auto()); + promise_.set_error(std::move(status)); + } +}; + class GetSavedRingtonesQuery final : public Td::ResultHandler { Promise> promise_; @@ -43,7 +103,7 @@ class GetSavedRingtonesQuery final : public Td::ResultHandler { } void send(int64 hash) { - send_query(G()->net_query_creator().create(telegram_api::account_getSavedRingtones(hash))); + send_query(G()->net_query_creator().create(telegram_api::account_getSavedRingtones(hash), {{"ringtone"}})); } void on_result(BufferSlice packet) final { @@ -654,6 +714,69 @@ vector NotificationSettingsManager::get_saved_ringtones(Promise && return saved_ringtone_file_ids_; } +void NotificationSettingsManager::send_save_ringtone_query( + FileId ringtone_file_id, bool unsave, + Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + + // TODO log event + auto file_view = td_->file_manager_->get_file_view(ringtone_file_id); + CHECK(!file_view.empty()); + CHECK(file_view.has_remote_location()); + CHECK(file_view.remote_location().is_document()); + CHECK(!file_view.remote_location().is_web()); + td_->create_handler(std::move(promise)) + ->send(ringtone_file_id, file_view.remote_location().as_input_document(), unsave); +} + +void NotificationSettingsManager::remove_saved_ringtone(int64 ringtone_id, Promise &&promise) { + if (!are_saved_ringtones_loaded_) { + reload_saved_ringtones(std::move(promise)); + return; + } + + for (auto &file_id : saved_ringtone_file_ids_) { + auto file_view = td_->file_manager_->get_file_view(file_id); + CHECK(!file_view.empty()); + CHECK(file_view.get_type() == FileType::Ringtone); + CHECK(file_view.has_remote_location()); + if (file_view.remote_location().get_id() == ringtone_id) { + send_save_ringtone_query( + file_view.file_id(), true, + PromiseCreator::lambda( + [actor_id = actor_id(this), ringtone_id, promise = std::move(promise)]( + Result> &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + send_closure(actor_id, &NotificationSettingsManager::on_remove_saved_ringtone, ringtone_id, + std::move(promise)); + } + })); + return; + } + } + + promise.set_value(Unit()); +} + +void NotificationSettingsManager::on_remove_saved_ringtone(int64 ringtone_id, Promise &&promise) { + CHECK(are_saved_ringtones_loaded_); + + for (auto it = saved_ringtone_file_ids_.begin(); it != saved_ringtone_file_ids_.begin(); ++it) { + auto file_view = td_->file_manager_->get_file_view(*it); + CHECK(!file_view.empty()); + CHECK(file_view.get_type() == FileType::Ringtone); + CHECK(file_view.has_remote_location()); + if (file_view.remote_location().get_id() == ringtone_id) { + saved_ringtone_file_ids_.erase(it); + break; + } + } + + promise.set_value(Unit()); +} + Result NotificationSettingsManager::get_ringtone( telegram_api::object_ptr &&ringtone) const { int32 document_id = ringtone->get_id(); diff --git a/td/telegram/NotificationSettingsManager.h b/td/telegram/NotificationSettingsManager.h index 9e3a8108b..4bb70e01d 100644 --- a/td/telegram/NotificationSettingsManager.h +++ b/td/telegram/NotificationSettingsManager.h @@ -50,8 +50,13 @@ class NotificationSettingsManager final : public Actor { vector get_saved_ringtones(Promise &&promise); + void remove_saved_ringtone(int64 ringtone_id, Promise &&promise); + void reload_saved_ringtones(Promise &&promise); + void send_save_ringtone_query(FileId ringtone_file_id, bool unsave, + Promise> &&promise); + void send_get_dialog_notification_settings_query(DialogId dialog_id, Promise &&promise); const ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope, @@ -97,6 +102,8 @@ class NotificationSettingsManager final : public Actor { Result get_ringtone(telegram_api::object_ptr &&ringtone) const; + void on_remove_saved_ringtone(int64 ringtone_id, Promise &&promise); + void on_reload_saved_ringtones(Result> &&result); ScopeNotificationSettings *get_scope_notification_settings(NotificationSettingsScope scope); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index badf68c26..073c15261 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2630,6 +2630,20 @@ class GetSavedNotificationSoundsRequest final : public RequestActor<> { } }; +class RemoveSavedNotificationSoundRequest final : public RequestOnceActor { + int64 ringtone_id_; + + void do_run(Promise &&promise) final { + td_->notification_settings_manager_->remove_saved_ringtone(ringtone_id_, std::move(promise)); + } + + public: + RemoveSavedNotificationSoundRequest(ActorShared td, uint64 request_id, int64 ringtone_id) + : RequestOnceActor(std::move(td), request_id), ringtone_id_(ringtone_id) { + set_tries(3); + } +}; + class GetInlineQueryResultsRequest final : public RequestOnceActor { UserId bot_user_id_; DialogId dialog_id_; @@ -4039,6 +4053,7 @@ void Td::init_managers() { notification_settings_manager_ = make_unique(this, create_reference()); notification_settings_manager_actor_ = register_actor("NotificationSettingsManager", notification_settings_manager_.get()); + G()->set_notification_settings_manager(notification_settings_manager_actor_.get()); poll_manager_ = make_unique(this, create_reference()); poll_manager_actor_ = register_actor("PollManager", poll_manager_.get()); sponsored_message_manager_ = make_unique(this, create_reference()); @@ -7141,6 +7156,11 @@ void Td::on_request(uint64 id, const td_api::getSavedNotificationSounds &request CREATE_NO_ARGS_REQUEST(GetSavedNotificationSoundsRequest); } +void Td::on_request(uint64 id, const td_api::removeSavedNotificationSound &request) { + CHECK_IS_USER(); + CREATE_REQUEST(RemoveSavedNotificationSoundRequest, request.notification_sound_id_); +} + void Td::on_request(uint64 id, const td_api::getChatNotificationSettingsExceptions &request) { CHECK_IS_USER(); bool filter_scope = false; diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 3b2440178..8a4257377 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1108,6 +1108,8 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getSavedNotificationSounds &request); + void on_request(uint64 id, const td_api::removeSavedNotificationSound &request); + void on_request(uint64 id, const td_api::getChatNotificationSettingsExceptions &request); void on_request(uint64 id, const td_api::getScopeNotificationSettings &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 708e80bc9..a4d81c877 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4491,9 +4491,15 @@ class CliClient final : public Actor { get_args(args, profile_photo_id); send_request(td_api::make_object(profile_photo_id)); } else if (op == "gns") { - send_request(td_api::make_object()); + int64 notification_sound_id; + get_args(args, notification_sound_id); + send_request(td_api::make_object(notification_sound_id)); } else if (op == "gnss") { send_request(td_api::make_object()); + } else if (op == "rns") { + int64 notification_sound_id; + get_args(args, notification_sound_id); + send_request(td_api::make_object(notification_sound_id)); } else if (op == "gcnse" || op == "gcnses") { send_request(td_api::make_object( get_notification_settings_scope(args), op == "gcnses"));