diff --git a/CMakeLists.txt b/CMakeLists.txt index f463608c1..7690676eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,6 +276,7 @@ set(TDLIB_SOURCE td/mtproto/Transport.cpp td/mtproto/utils.cpp + td/telegram/Account.cpp td/telegram/AnimationsManager.cpp td/telegram/AudiosManager.cpp td/telegram/AuthManager.cpp @@ -453,6 +454,7 @@ set(TDLIB_SOURCE td/mtproto/utils.h td/telegram/AccessRights.h + td/telegram/Account.h td/telegram/AffectedHistory.h td/telegram/AnimationsManager.h td/telegram/AudiosManager.h diff --git a/td/telegram/Account.cpp b/td/telegram/Account.cpp new file mode 100644 index 000000000..51695fb14 --- /dev/null +++ b/td/telegram/Account.cpp @@ -0,0 +1,255 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/Account.h" + +#include "td/telegram/DeviceTokenManager.h" +#include "td/telegram/Global.h" +#include "td/telegram/net/NetQueryCreator.h" +#include "td/telegram/Td.h" +#include "td/telegram/telegram_api.h" + +#include "td/actor/actor.h" + +#include "td/utils/algorithm.h" +#include "td/utils/base64.h" +#include "td/utils/buffer.h" +#include "td/utils/logging.h" +#include "td/utils/misc.h" +#include "td/utils/Slice.h" +#include "td/utils/Status.h" + +#include + +namespace td { + +static td_api::object_ptr convert_authorization_object( + tl_object_ptr &&authorization) { + CHECK(authorization != nullptr); + return td_api::make_object( + authorization->hash_, authorization->current_, authorization->password_pending_, authorization->api_id_, + authorization->app_name_, authorization->app_version_, authorization->official_app_, authorization->device_model_, + authorization->platform_, authorization->system_version_, authorization->date_created_, + authorization->date_active_, authorization->ip_, authorization->country_, authorization->region_); +} + +class SetAccountTtlQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit SetAccountTtlQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(int32 account_ttl) { + send_query(G()->net_query_creator().create( + telegram_api::account_setAccountTTL(make_tl_object(account_ttl)))); + } + + 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()); + } + + bool result = result_ptr.move_as_ok(); + if (!result) { + return on_error(Status::Error(500, "Internal Server Error: failed to set account TTL")); + } + + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +class GetAccountTtlQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit GetAccountTtlQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create(telegram_api::account_getAccountTTL())); + } + + 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 ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetAccountTtlQuery: " << to_string(ptr); + + promise_.set_value(std::move(ptr->days_)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +class AcceptLoginTokenQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit AcceptLoginTokenQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(const string &login_token) { + send_query(G()->net_query_creator().create(telegram_api::auth_acceptLoginToken(BufferSlice(login_token)))); + } + + 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()); + } + + LOG(DEBUG) << "Receive result for AcceptLoginTokenQuery: " << to_string(result_ptr.ok()); + promise_.set_value(convert_authorization_object(result_ptr.move_as_ok())); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +class GetAuthorizationsQuery final : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetAuthorizationsQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create(telegram_api::account_getAuthorizations())); + } + + 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 ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetAuthorizationsQuery: " << to_string(ptr); + + auto results = + make_tl_object(transform(std::move(ptr->authorizations_), convert_authorization_object)); + std::sort(results->sessions_.begin(), results->sessions_.end(), + [](const td_api::object_ptr &lhs, const td_api::object_ptr &rhs) { + if (lhs->is_current_ != rhs->is_current_) { + return lhs->is_current_; + } + if (lhs->is_password_pending_ != rhs->is_password_pending_) { + return lhs->is_password_pending_; + } + return lhs->last_active_date_ > rhs->last_active_date_; + }); + + promise_.set_value(std::move(results)); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +class ResetAuthorizationQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit ResetAuthorizationQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send(int64 authorization_id) { + send_query(G()->net_query_creator().create(telegram_api::account_resetAuthorization(authorization_id))); + } + + 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()); + } + + bool result = result_ptr.move_as_ok(); + LOG_IF(WARNING, !result) << "Failed to terminate session"; + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +class ResetAuthorizationsQuery final : public Td::ResultHandler { + Promise promise_; + + public: + explicit ResetAuthorizationsQuery(Promise &&promise) : promise_(std::move(promise)) { + } + + void send() { + send_query(G()->net_query_creator().create(telegram_api::auth_resetAuthorizations())); + } + + 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()); + } + + bool result = result_ptr.move_as_ok(); + LOG_IF(WARNING, !result) << "Failed to terminate all sessions"; + send_closure(td_->device_token_manager_, &DeviceTokenManager::reregister_device); + promise_.set_value(Unit()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + +void set_account_ttl(Td *td, int32 account_ttl, Promise &&promise) { + td->create_handler(std::move(promise))->send(account_ttl); +} + +void get_account_ttl(Td *td, Promise &&promise) { + td->create_handler(std::move(promise))->send(); +} + +void confirm_qr_code_authentication(Td *td, const string &link, + Promise> &&promise) { + Slice prefix("tg://login?token="); + if (!begins_with(to_lower(link), prefix)) { + return promise.set_error(Status::Error(400, "AUTH_TOKEN_INVALID")); + } + auto r_token = base64url_decode(Slice(link).substr(prefix.size())); + if (r_token.is_error()) { + return promise.set_error(Status::Error(400, "AUTH_TOKEN_INVALID")); + } + td->create_handler(std::move(promise))->send(r_token.ok()); +} + +void get_active_sessions(Td *td, Promise> &&promise) { + td->create_handler(std::move(promise))->send(); +} + +void terminate_session(Td *td, int64 session_id, Promise &&promise) { + td->create_handler(std::move(promise))->send(session_id); +} + +void terminate_all_other_sessions(Td *td, Promise &&promise) { + td->create_handler(std::move(promise))->send(); +} + +} // namespace td diff --git a/td/telegram/Account.h b/td/telegram/Account.h new file mode 100644 index 000000000..288a3ee2c --- /dev/null +++ b/td/telegram/Account.h @@ -0,0 +1,31 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" + +#include "td/actor/PromiseFuture.h" + +#include "td/utils/common.h" + +namespace td { + +class Td; + +void set_account_ttl(Td *td, int32 account_ttl, Promise &&promise); + +void get_account_ttl(Td *td, Promise &&promise); + +void confirm_qr_code_authentication(Td *td, const string &link, Promise> &&promise); + +void get_active_sessions(Td *td, Promise> &&promise); + +void terminate_session(Td *td, int64 session_id, Promise &&promise); + +void terminate_all_other_sessions(Td *td, Promise &&promise); + +} // namespace td diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index ea2966ab4..31c9594bf 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -54,7 +54,6 @@ #include "td/actor/SleepActor.h" #include "td/utils/algorithm.h" -#include "td/utils/base64.h" #include "td/utils/buffer.h" #include "td/utils/format.h" #include "td/utils/logging.h" @@ -106,188 +105,6 @@ class DismissSuggestionQuery final : public Td::ResultHandler { } }; -class SetAccountTtlQuery final : public Td::ResultHandler { - Promise promise_; - - public: - explicit SetAccountTtlQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send(int32 account_ttl) { - send_query(G()->net_query_creator().create( - telegram_api::account_setAccountTTL(make_tl_object(account_ttl)))); - } - - 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()); - } - - bool result = result_ptr.move_as_ok(); - if (!result) { - return on_error(Status::Error(500, "Internal Server Error: failed to set account TTL")); - } - - promise_.set_value(Unit()); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - -class GetAccountTtlQuery final : public Td::ResultHandler { - Promise promise_; - - public: - explicit GetAccountTtlQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send() { - send_query(G()->net_query_creator().create(telegram_api::account_getAccountTTL())); - } - - 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 ptr = result_ptr.move_as_ok(); - LOG(INFO) << "Receive result for GetAccountTtlQuery: " << to_string(ptr); - - promise_.set_value(std::move(ptr->days_)); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - -class AcceptLoginTokenQuery final : public Td::ResultHandler { - Promise> promise_; - - public: - explicit AcceptLoginTokenQuery(Promise> &&promise) - : promise_(std::move(promise)) { - } - - void send(const string &login_token) { - send_query(G()->net_query_creator().create(telegram_api::auth_acceptLoginToken(BufferSlice(login_token)))); - } - - 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()); - } - - LOG(DEBUG) << "Receive result for AcceptLoginTokenQuery: " << to_string(result_ptr.ok()); - promise_.set_value(ContactsManager::convert_authorization_object(result_ptr.move_as_ok())); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - -class GetAuthorizationsQuery final : public Td::ResultHandler { - Promise> promise_; - - public: - explicit GetAuthorizationsQuery(Promise> &&promise) : promise_(std::move(promise)) { - } - - void send() { - send_query(G()->net_query_creator().create(telegram_api::account_getAuthorizations())); - } - - 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 ptr = result_ptr.move_as_ok(); - LOG(INFO) << "Receive result for GetAuthorizationsQuery: " << to_string(ptr); - - auto results = make_tl_object( - transform(std::move(ptr->authorizations_), ContactsManager::convert_authorization_object)); - std::sort(results->sessions_.begin(), results->sessions_.end(), - [](const td_api::object_ptr &lhs, const td_api::object_ptr &rhs) { - if (lhs->is_current_ != rhs->is_current_) { - return lhs->is_current_; - } - if (lhs->is_password_pending_ != rhs->is_password_pending_) { - return lhs->is_password_pending_; - } - return lhs->last_active_date_ > rhs->last_active_date_; - }); - - promise_.set_value(std::move(results)); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - -class ResetAuthorizationQuery final : public Td::ResultHandler { - Promise promise_; - - public: - explicit ResetAuthorizationQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send(int64 authorization_id) { - send_query(G()->net_query_creator().create(telegram_api::account_resetAuthorization(authorization_id))); - } - - 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()); - } - - bool result = result_ptr.move_as_ok(); - LOG_IF(WARNING, !result) << "Failed to terminate session"; - promise_.set_value(Unit()); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - -class ResetAuthorizationsQuery final : public Td::ResultHandler { - Promise promise_; - - public: - explicit ResetAuthorizationsQuery(Promise &&promise) : promise_(std::move(promise)) { - } - - void send() { - send_query(G()->net_query_creator().create(telegram_api::auth_resetAuthorizations())); - } - - 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()); - } - - bool result = result_ptr.move_as_ok(); - LOG_IF(WARNING, !result) << "Failed to terminate all sessions"; - send_closure(td_->device_token_manager_, &DeviceTokenManager::reregister_device); - promise_.set_value(Unit()); - } - - void on_error(Status status) final { - promise_.set_error(std::move(status)); - } -}; - class GetWebAuthorizationsQuery final : public Td::ResultHandler { Promise> promise_; @@ -5223,49 +5040,6 @@ td_api::object_ptr ContactsManager::get_check_c } } -void ContactsManager::set_account_ttl(int32 account_ttl, Promise &&promise) const { - td_->create_handler(std::move(promise))->send(account_ttl); -} - -void ContactsManager::get_account_ttl(Promise &&promise) const { - td_->create_handler(std::move(promise))->send(); -} - -td_api::object_ptr ContactsManager::convert_authorization_object( - tl_object_ptr &&authorization) { - CHECK(authorization != nullptr); - return td_api::make_object( - authorization->hash_, authorization->current_, authorization->password_pending_, authorization->api_id_, - authorization->app_name_, authorization->app_version_, authorization->official_app_, authorization->device_model_, - authorization->platform_, authorization->system_version_, authorization->date_created_, - authorization->date_active_, authorization->ip_, authorization->country_, authorization->region_); -} - -void ContactsManager::confirm_qr_code_authentication(const string &link, - Promise> &&promise) { - Slice prefix("tg://login?token="); - if (!begins_with(to_lower(link), prefix)) { - return promise.set_error(Status::Error(400, "AUTH_TOKEN_INVALID")); - } - auto r_token = base64url_decode(Slice(link).substr(prefix.size())); - if (r_token.is_error()) { - return promise.set_error(Status::Error(400, "AUTH_TOKEN_INVALID")); - } - td_->create_handler(std::move(promise))->send(r_token.ok()); -} - -void ContactsManager::get_active_sessions(Promise> &&promise) const { - td_->create_handler(std::move(promise))->send(); -} - -void ContactsManager::terminate_session(int64 session_id, Promise &&promise) const { - td_->create_handler(std::move(promise))->send(session_id); -} - -void ContactsManager::terminate_all_other_sessions(Promise &&promise) const { - td_->create_handler(std::move(promise))->send(); -} - void ContactsManager::get_connected_websites(Promise> &&promise) const { td_->create_handler(std::move(promise))->send(); } diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 5abd303dd..b9edd83a8 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -273,18 +273,6 @@ class ContactsManager final : public Actor { static td_api::object_ptr get_check_chat_username_result_object( CheckDialogUsernameResult result); - void set_account_ttl(int32 account_ttl, Promise &&promise) const; - void get_account_ttl(Promise &&promise) const; - - static td_api::object_ptr convert_authorization_object( - tl_object_ptr &&authorization); - - void confirm_qr_code_authentication(const string &link, Promise> &&promise); - - void get_active_sessions(Promise> &&promise) const; - void terminate_session(int64 session_id, Promise &&promise) const; - void terminate_all_other_sessions(Promise &&promise) const; - void get_connected_websites(Promise> &&promise) const; void disconnect_website(int64 website_id, Promise &&promise) const; void disconnect_all_websites(Promise &&promise) const; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8d315b595..2a924a21c 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/Td.h" +#include "td/telegram/Account.h" #include "td/telegram/AnimationsManager.h" #include "td/telegram/AudiosManager.h" #include "td/telegram/AuthManager.h" @@ -4538,7 +4539,7 @@ void Td::on_request(uint64 id, td_api::checkAuthenticationBotToken &request) { void Td::on_request(uint64 id, td_api::confirmQrCodeAuthentication &request) { CLEAN_INPUT_STRING(request.link_); CREATE_REQUEST_PROMISE(); - contacts_manager_->confirm_qr_code_authentication(request.link_, std::move(promise)); + confirm_qr_code_authentication(this, request.link_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::getCurrentState &request) { @@ -4733,7 +4734,7 @@ void Td::on_request(uint64 id, const td_api::getAccountTtl &request) { promise.set_value(td_api::make_object(result.ok())); } }); - contacts_manager_->get_account_ttl(std::move(query_promise)); + get_account_ttl(this, std::move(query_promise)); } void Td::on_request(uint64 id, const td_api::setAccountTtl &request) { @@ -4742,7 +4743,7 @@ void Td::on_request(uint64 id, const td_api::setAccountTtl &request) { return send_error_raw(id, 400, "New account TTL must be non-empty"); } CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_account_ttl(request.ttl_->days_, std::move(promise)); + set_account_ttl(this, request.ttl_->days_, std::move(promise)); } void Td::on_request(uint64 id, td_api::deleteAccount &request) { @@ -4772,19 +4773,19 @@ void Td::on_request(uint64 id, td_api::resendChangePhoneNumberCode &request) { void Td::on_request(uint64 id, const td_api::getActiveSessions &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); - contacts_manager_->get_active_sessions(std::move(promise)); + get_active_sessions(this, std::move(promise)); } void Td::on_request(uint64 id, const td_api::terminateSession &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->terminate_session(request.session_id_, std::move(promise)); + terminate_session(this, request.session_id_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::terminateAllOtherSessions &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->terminate_all_other_sessions(std::move(promise)); + terminate_all_other_sessions(this, std::move(promise)); } void Td::on_request(uint64 id, const td_api::getConnectedWebsites &request) {