diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2b7208b77..9f2edef06 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3043,7 +3043,7 @@ setAccountTtl ttl:accountTtl = Ok; //@description Returns the period of inactivity after which the account of the current user will automatically be deleted getAccountTtl = AccountTtl; -//@description Deletes the account of the current user, deleting all information associated with the user from the server. The phone number of the account can be used to create a new account @reason The reason why the account was deleted; optional +//@description Deletes the account of the current user, deleting all information associated with the user from the server. The phone number of the account can be used to create a new account. Can be called before authorization when the current authorization state is authorizationStateWaitPassword @reason The reason why the account was deleted; optional deleteAccount reason:string = Ok; @@ -3133,6 +3133,17 @@ getPassportAuthorizationForm bot_user_id:int32 scope:string public_key:string pa sendPassportAuthorizationForm autorization_form_id:int32 types:vector password:string = Ok; +//@description Sends phone number comfirmation code. Should be called when user presses "https://t.me/confirmphone?phone=*******&hash=**********" or "tg://confirmphone?phone=*******&hash=**********" link @hash "Hash" parameter from the link +//@phone_number "Phone" parameter from the link @allow_flash_call Pass true if the authentication code may be sent via flash call to the specified phone number @is_current_phone_number Pass true if the phone number is used on the current device. Ignored if allow_flash_call is false +sendPhoneNumberConfirmationCode hash:string phone_number:string allow_flash_call:Bool is_current_phone_number:Bool = AuthenticationCodeInfo; + +//@description Resends phone number comfirmation code +resendPhoneNumberConfirmationCode = AuthenticationCodeInfo; + +//@description Checks phone number comfirmation code @code The phone number confirmation code +checkPhoneNumberConfirmationCode code:string = Ok; + + //@description Informs the server about the number of pending bot updates if they haven't been processed for a long time; for bots only @pending_update_count The number of pending updates @error_message The last error message setBotUpdatesStatus pending_update_count:int32 error_message:string = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index c9891a99a..55d5c9c00 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index 91498a6af..c34b6bf95 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -91,7 +91,8 @@ Result SendCodeHelper::send_change_ph return telegram_api::account_sendChangePhoneCode(flags, false /*ignored*/, phone_number_, is_current_phone_number); } -Result SendCodeHelper::send_verify_phone_code(Slice phone_number, +Result SendCodeHelper::send_verify_phone_code(const string &hash, + Slice phone_number, bool allow_flash_call, bool is_current_phone_number) { phone_number_ = phone_number.str(); @@ -99,7 +100,7 @@ Result SendCodeHelper::send_verify_ph if (allow_flash_call) { flags |= AUTH_SEND_CODE_FLAG_ALLOW_FLASH_CALL; } - return telegram_api::account_sendVerifyPhoneCode(flags, false /*ignored*/, phone_number_, is_current_phone_number); + return telegram_api::account_sendVerifyPhoneCode(flags, false /*ignored*/, hash, is_current_phone_number); } Result SendCodeHelper::send_confirm_phone_code( @@ -216,12 +217,30 @@ void PhoneNumberManager::set_phone_number(uint64 query_id, string phone_number, case Type::ChangePhone: return process_send_code_result( query_id, send_code_helper_.send_change_phone_code(phone_number, allow_flash_call, is_current_phone_number)); - case Type::VerifyPhone: - return process_send_code_result( - query_id, send_code_helper_.send_verify_phone_code(phone_number, allow_flash_call, is_current_phone_number)); case Type::ConfirmPhone: return process_send_code_result( query_id, send_code_helper_.send_confirm_phone_code(phone_number, allow_flash_call, is_current_phone_number)); + case Type::VerifyPhone: + default: + UNREACHABLE(); + } +} + +void PhoneNumberManager::set_phone_number_and_hash(uint64 query_id, string hash, string phone_number, + bool allow_flash_call, bool is_current_phone_number) { + if (phone_number.empty()) { + return on_query_error(query_id, Status::Error(8, "Phone number can't be empty")); + } + if (hash.empty()) { + return on_query_error(query_id, Status::Error(8, "Hash can't be empty")); + } + + switch (type_) { + case Type::VerifyPhone: + return process_send_code_result(query_id, send_code_helper_.send_verify_phone_code( + hash, phone_number, allow_flash_call, is_current_phone_number)); + case Type::ChangePhone: + case Type::ConfirmPhone: default: UNREACHABLE(); } @@ -649,14 +668,14 @@ void AuthManager::logout(uint64 query_id) { } void AuthManager::delete_account(uint64 query_id, const string &reason) { - if (state_ != State::Ok) { + if (state_ != State::Ok && state_ != State::WaitPassword) { return on_query_error(query_id, Status::Error(8, "Need to log in first")); } on_new_query(query_id); LOG(INFO) << "Deleting account"; - update_state(State::LoggingOut); start_net_query(NetQueryType::DeleteAccount, - G()->net_query_creator().create(create_storer(telegram_api::account_deleteAccount(reason)))); + G()->net_query_creator().create(create_storer(telegram_api::account_deleteAccount(reason)), + DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off)); } void AuthManager::on_closing() { @@ -807,13 +826,13 @@ void AuthManager::on_delete_account_result(NetQueryPtr &result) { status = std::move(result->error()); } if (status.is_error() && status.error().message() != "USER_DEACTIVATED") { - update_state(State::Ok); LOG(WARNING) << "account.deleteAccount failed: " << status; // TODO handle some errors if (query_id_ != 0) { on_query_error(std::move(status)); } } else { + update_state(State::LoggingOut); send_closure_later(G()->td(), &Td::destroy); if (query_id_ != 0) { on_query_ok(); diff --git a/td/telegram/AuthManager.h b/td/telegram/AuthManager.h index 033e25edb..d5f347130 100644 --- a/td/telegram/AuthManager.h +++ b/td/telegram/AuthManager.h @@ -34,7 +34,8 @@ class SendCodeHelper { Result send_change_phone_code(Slice phone_number, bool allow_flash_call, bool is_current_phone_number); - Result send_verify_phone_code(Slice phone_number, bool allow_flash_call, + Result send_verify_phone_code(const string &hash, Slice phone_number, + bool allow_flash_call, bool is_current_phone_number); Result send_confirm_phone_code(Slice phone_number, bool allow_flash_call, @@ -103,6 +104,8 @@ class PhoneNumberManager : public NetActor { void get_state(uint64 query_id); void set_phone_number(uint64 query_id, string phone_number, bool allow_flash_call, bool is_current_phone_number); + void set_phone_number_and_hash(uint64 query_id, string hash, string phone_number, bool allow_flash_call, + bool is_current_phone_number); void resend_authentication_code(uint64 query_id); void check_code(uint64 query_id, string code); diff --git a/td/telegram/StorageManager.cpp b/td/telegram/StorageManager.cpp index de68743e6..bd5721277 100644 --- a/td/telegram/StorageManager.cpp +++ b/td/telegram/StorageManager.cpp @@ -23,6 +23,7 @@ #include "td/utils/Time.h" namespace td { + StorageManager::StorageManager(ActorShared<> parent, int32 scheduler_id) : parent_(std::move(parent)), scheduler_id_(scheduler_id) { } diff --git a/td/telegram/StorageManager.h b/td/telegram/StorageManager.h index 48185b908..0d9f80ecf 100644 --- a/td/telegram/StorageManager.h +++ b/td/telegram/StorageManager.h @@ -21,6 +21,7 @@ class FileGcWorker; } // namespace td namespace td { + class StorageManager : public Actor { public: StorageManager(ActorShared<> parent, int32 scheduler_id); @@ -79,4 +80,5 @@ class StorageManager : public Actor { void timeout_expired() override; }; + } // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 798f48c78..59fa68662 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3974,6 +3974,7 @@ bool Td::is_authentication_request(int32 id) { case td_api::checkAuthenticationPassword::ID: case td_api::requestAuthenticationPasswordRecovery::ID: case td_api::recoverAuthenticationPassword::ID: + case td_api::deleteAccount::ID: case td_api::logOut::ID: case td_api::close::ID: case td_api::destroy::ID: @@ -4502,14 +4503,14 @@ void Td::clear() { LOG(DEBUG) << "Requests was answered " << timer; // close all pure actors - change_phone_number_manager_.reset(); - LOG(DEBUG) << "ChangePhoneNumberManager was cleared " << timer; - verify_phone_number_manager_.reset(); - LOG(DEBUG) << "ChangePhoneNumberManager was cleared " << timer; call_manager_.reset(); LOG(DEBUG) << "CallManager was cleared " << timer; + change_phone_number_manager_.reset(); + LOG(DEBUG) << "ChangePhoneNumberManager was cleared " << timer; config_manager_.reset(); LOG(DEBUG) << "ConfigManager was cleared " << timer; + confirm_phone_number_manager_.reset(); + LOG(DEBUG) << "ConfirmPhoneNumberManager was cleared " << timer; device_token_manager_.reset(); LOG(DEBUG) << "DeviceTokenManager was cleared " << timer; hashtag_hints_.reset(); @@ -4528,6 +4529,8 @@ void Td::clear() { LOG(DEBUG) << "StorageManager was cleared " << timer; top_dialog_manager_.reset(); LOG(DEBUG) << "TopDialogManager was cleared " << timer; + verify_phone_number_manager_.reset(); + LOG(DEBUG) << "VerifyPhoneNumberManager was cleared " << timer; G()->set_connection_creator(ActorOwn()); LOG(DEBUG) << "ConnectionCreator was cleared " << timer; @@ -4811,25 +4814,27 @@ Status Td::init(DbKey key) { web_pages_manager_actor_ = register_actor("WebPagesManager", web_pages_manager_.get()); G()->set_web_pages_manager(web_pages_manager_actor_.get()); - change_phone_number_manager_ = create_actor( - "ChangePhoneNumberManager", PhoneNumberManager::Type::ChangePhone, create_reference()); - verify_phone_number_manager_ = create_actor( - "VerifyPhoneNumberManager", PhoneNumberManager::Type::VerifyPhone, create_reference()); call_manager_ = create_actor("CallManager", create_reference()); G()->set_call_manager(call_manager_.get()); + change_phone_number_manager_ = create_actor( + "ChangePhoneNumberManager", PhoneNumberManager::Type::ChangePhone, create_reference()); + confirm_phone_number_manager_ = create_actor( + "ConfirmPhoneNumberManager", PhoneNumberManager::Type::ConfirmPhone, create_reference()); device_token_manager_ = create_actor("DeviceTokenManager", create_reference()); hashtag_hints_ = create_actor("HashtagHints", "text", create_reference()); password_manager_ = create_actor("PasswordManager", create_reference()); G()->set_password_manager(password_manager_.get()); privacy_manager_ = create_actor("PrivacyManager", create_reference()); - secure_manager_ = create_actor("SecureManager", create_reference()); secret_chats_manager_ = create_actor("SecretChatsManager", create_reference()); G()->set_secret_chats_manager(secret_chats_manager_.get()); + secure_manager_ = create_actor("SecureManager", create_reference()); storage_manager_ = create_actor("StorageManager", create_reference(), min(current_scheduler_id + 2, scheduler_count - 1)); G()->set_storage_manager(storage_manager_.get()); top_dialog_manager_ = create_actor("TopDialogManager", create_reference()); G()->set_top_dialog_manager(top_dialog_manager_.get()); + verify_phone_number_manager_ = create_actor( + "VerifyPhoneNumberManager", PhoneNumberManager::Type::VerifyPhone, create_reference()); VLOG(td_init) << "Send binlog events"; for (auto &event : events.user_events) { @@ -6987,6 +6992,26 @@ void Td::on_request(uint64 id, td_api::sendPassportAuthorizationForm &request) { request.autorization_form_id_, get_secure_value_types_td_api(request.types_), std::move(promise)); } +void Td::on_request(uint64 id, td_api::sendPhoneNumberConfirmationCode &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.phone_number_); + CLEAN_INPUT_STRING(request.hash_); + send_closure(confirm_phone_number_manager_, &PhoneNumberManager::set_phone_number_and_hash, id, + std::move(request.hash_), std::move(request.phone_number_), request.allow_flash_call_, + request.is_current_phone_number_); +} + +void Td::on_request(uint64 id, const td_api::resendPhoneNumberConfirmationCode &request) { + CHECK_IS_USER(); + send_closure(confirm_phone_number_manager_, &PhoneNumberManager::resend_authentication_code, id); +} + +void Td::on_request(uint64 id, td_api::checkPhoneNumberConfirmationCode &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.code_); + send_closure(confirm_phone_number_manager_, &PhoneNumberManager::check_code, id, std::move(request.code_)); +} + void Td::on_request(uint64 id, const td_api::getSupportUser &request) { CHECK_IS_USER(); CREATE_NO_ARGS_REQUEST(GetSupportUserRequest); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index cf4fa7dd1..32348030e 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -145,10 +145,10 @@ class Td final : public NetQueryCallback { std::unique_ptr web_pages_manager_; ActorOwn web_pages_manager_actor_; - ActorOwn change_phone_number_manager_; - ActorOwn verify_phone_number_manager_; ActorOwn call_manager_; + ActorOwn change_phone_number_manager_; ActorOwn config_manager_; + ActorOwn confirm_phone_number_manager_; ActorOwn device_token_manager_; ActorOwn hashtag_hints_; ActorOwn net_stats_manager_; @@ -159,6 +159,7 @@ class Td final : public NetQueryCallback { ActorOwn state_manager_; ActorOwn storage_manager_; ActorOwn top_dialog_manager_; + ActorOwn verify_phone_number_manager_; class ResultHandler : public std::enable_shared_from_this { public: @@ -799,6 +800,12 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::sendPassportAuthorizationForm &request); + void on_request(uint64 id, td_api::sendPhoneNumberConfirmationCode &request); + + void on_request(uint64 id, const td_api::resendPhoneNumberConfirmationCode &request); + + void on_request(uint64 id, td_api::checkPhoneNumberConfirmationCode &request); + void on_request(uint64 id, const td_api::getSupportUser &request); void on_request(uint64 id, const td_api::getWallpapers &request); diff --git a/td/telegram/TopDialogManager.cpp b/td/telegram/TopDialogManager.cpp index bfc32ef3a..cbe2b2b0d 100644 --- a/td/telegram/TopDialogManager.cpp +++ b/td/telegram/TopDialogManager.cpp @@ -515,7 +515,7 @@ void TopDialogManager::on_first_sync() { } void TopDialogManager::loop() { - if (!is_active_) { + if (!is_active_ || G()->close_flag()) { return; } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index dfe6b7ee2..a41cfae61 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1266,6 +1266,12 @@ class CliClient final : public Actor { string recovery_email_address; std::tie(password, recovery_email_address) = split(args); send_request(make_tl_object(password, recovery_email_address)); + } else if (op == "spncc") { + send_request(make_tl_object(args, false, false)); + } else if (op == "cpncc") { + send_request(make_tl_object(args)); + } else if (op == "rpncc") { + send_request(make_tl_object()); } else if (op == "rpr" || op == "RequestPasswordRecovery") { send_request(make_tl_object()); } else if (op == "rp" || op == "RecoverPassword") { diff --git a/td/telegram/net/NetQueryDelayer.cpp b/td/telegram/net/NetQueryDelayer.cpp index 76e169697..9c19471db 100644 --- a/td/telegram/net/NetQueryDelayer.cpp +++ b/td/telegram/net/NetQueryDelayer.cpp @@ -27,14 +27,10 @@ void NetQueryDelayer::delay(NetQueryPtr query) { // skip } else if (code == 420) { auto msg = query->error().message(); - auto prefix = Slice("FLOOD_WAIT_"); - if (msg.substr(0, prefix.size()) == prefix) { - timeout = to_integer(msg.substr(prefix.size())); - if (timeout < 0) { - timeout = 0; - } - if (timeout > 24 * 60 * 60) { - timeout = 24 * 60 * 60; + for (auto prefix : {Slice("FLOOD_WAIT_"), Slice("2FA_CONFIRM_WAIT_"), Slice("TAKEOUT_INIT_DELAY_")}) { + if (begins_with(msg, prefix)) { + timeout = clamp(to_integer(msg.substr(prefix.size())), 0, 14 * 24 * 60 * 60); + break; } } } else {