Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
e8c9db61d0
@ -6,7 +6,7 @@ if (POLICY CMP0065)
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
endif()
|
||||
|
||||
project(TDLib VERSION 1.7.4 LANGUAGES CXX C)
|
||||
project(TDLib VERSION 1.7.5 LANGUAGES CXX C)
|
||||
|
||||
if (NOT DEFINED CMAKE_MODULE_PATH)
|
||||
set(CMAKE_MODULE_PATH "")
|
||||
@ -375,6 +375,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/net/Session.cpp
|
||||
td/telegram/net/SessionProxy.cpp
|
||||
td/telegram/net/SessionMultiProxy.cpp
|
||||
td/telegram/NewPasswordState.cpp
|
||||
td/telegram/NotificationManager.cpp
|
||||
td/telegram/NotificationSettings.cpp
|
||||
td/telegram/NotificationType.cpp
|
||||
@ -569,6 +570,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/net/SessionProxy.h
|
||||
td/telegram/net/SessionMultiProxy.h
|
||||
td/telegram/net/TempAuthKeyWatchdog.h
|
||||
td/telegram/NewPasswordState.h
|
||||
td/telegram/Notification.h
|
||||
td/telegram/NotificationGroupId.h
|
||||
td/telegram/NotificationGroupKey.h
|
||||
|
@ -217,7 +217,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||
|
||||
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
||||
```
|
||||
find_package(Td 1.7.4 REQUIRED)
|
||||
find_package(Td 1.7.5 REQUIRED)
|
||||
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||
```
|
||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
||||
|
||||
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
find_package(Td 1.7.4 REQUIRED)
|
||||
find_package(Td 1.7.5 REQUIRED)
|
||||
|
||||
add_executable(tdjson_example tdjson_example.cpp)
|
||||
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
||||
<Metadata>
|
||||
<Identity Id="Telegram.Td.UWP" Version="1.7.4" Language="en-US" Publisher="Telegram LLC" />
|
||||
<Identity Id="Telegram.Td.UWP" Version="1.7.5" Language="en-US" Publisher="Telegram LLC" />
|
||||
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
||||
<Description>TDLib is a library for building Telegram clients</Description>
|
||||
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
||||
|
@ -119,7 +119,8 @@ authorizationStateClosed = AuthorizationState;
|
||||
//@description Represents the current state of 2-step verification @has_password True, if a 2-step verification password is set @password_hint Hint for the password; may be empty
|
||||
//@has_recovery_email_address True, if a recovery email is set @has_passport_data True, if some Telegram Passport elements were saved
|
||||
//@recovery_email_address_code_info Information about the recovery email address to which the confirmation email was sent; may be null
|
||||
passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool recovery_email_address_code_info:emailAddressAuthenticationCodeInfo = PasswordState;
|
||||
//@pending_reset_date If not 0, point in time (Unix timestamp) after which the password can be reset immediately using resetPassword
|
||||
passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool recovery_email_address_code_info:emailAddressAuthenticationCodeInfo pending_reset_date:int32 = PasswordState;
|
||||
|
||||
//@description Contains information about the current recovery email address @recovery_email_address Recovery email address
|
||||
recoveryEmailAddress recovery_email_address:string = RecoveryEmailAddress;
|
||||
@ -2717,6 +2718,18 @@ checkStickerSetNameResultNameInvalid = CheckStickerSetNameResult;
|
||||
checkStickerSetNameResultNameOccupied = CheckStickerSetNameResult;
|
||||
|
||||
|
||||
//@class ResetPasswordResult @description Represents result of 2-step verification password reset
|
||||
|
||||
//@description The password was reset
|
||||
resetPasswordResultOk = ResetPasswordResult;
|
||||
|
||||
//@description The password reset request is pending @pending_reset_date Point in time (Unix timestamp) after which the password can be reset immediately using resetPassword
|
||||
resetPasswordResultPending pending_reset_date:int32 = ResetPasswordResult;
|
||||
|
||||
//@description The password reset request was declined @retry_date Point in time (Unix timestamp) when the password reset can be retried
|
||||
resetPasswordResultDeclined retry_date:int32 = ResetPasswordResult;
|
||||
|
||||
|
||||
//@class MessageFileType @description Contains information about a file with messages exported from another app
|
||||
|
||||
//@description The messages was exported from a private chat @name Name of the other party; may be empty if unrecognized
|
||||
@ -3877,8 +3890,12 @@ checkAuthenticationPassword password:string = Ok;
|
||||
//@description Requests to send a password recovery code to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword
|
||||
requestAuthenticationPasswordRecovery = Ok;
|
||||
|
||||
//@description Recovers the password with a password recovery code sent to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword @recovery_code Recovery code to check
|
||||
recoverAuthenticationPassword recovery_code:string = Ok;
|
||||
//@description Checks whether a password recovery code sent to an email address is valid. Works only when the current authorization state is authorizationStateWaitPassword @recovery_code Recovery code to check
|
||||
checkAuthenticationPasswordRecoveryCode recovery_code:string = Ok;
|
||||
|
||||
//@description Recovers the password with a password recovery code sent to an email address that was previously set up. Works only when the current authorization state is authorizationStateWaitPassword
|
||||
//@recovery_code Recovery code to check @new_password New password of the user; may be empty to remove the password @new_hint New password hint; may be empty
|
||||
recoverAuthenticationPassword recovery_code:string new_password:string new_hint:string = Ok;
|
||||
|
||||
//@description Checks the authentication token of a bot; to log in as a bot. Works only when the current authorization state is authorizationStateWaitPhoneNumber. Can be used instead of setAuthenticationPhoneNumber and checkAuthenticationCode to log in @token The bot token
|
||||
checkAuthenticationBotToken token:string = Ok;
|
||||
@ -3925,11 +3942,21 @@ checkRecoveryEmailAddressCode code:string = PasswordState;
|
||||
//@description Resends the 2-step verification recovery email address verification code
|
||||
resendRecoveryEmailAddressCode = PasswordState;
|
||||
|
||||
//@description Requests to send a password recovery code to an email address that was previously set up
|
||||
//@description Requests to send a 2-step verification password recovery code to an email address that was previously set up
|
||||
requestPasswordRecovery = EmailAddressAuthenticationCodeInfo;
|
||||
|
||||
//@description Recovers the password using a recovery code sent to an email address that was previously set up @recovery_code Recovery code to check
|
||||
recoverPassword recovery_code:string = PasswordState;
|
||||
//@description Checks whether a 2-step verification password recovery code sent to an email address is valid @recovery_code Recovery code to check
|
||||
checkPasswordRecoveryCode recovery_code:string = Ok;
|
||||
|
||||
//@description Recovers the 2-step verification password using a recovery code sent to an email address that was previously set up
|
||||
//@recovery_code Recovery code to check @new_password New password of the user; may be empty to remove the password @new_hint New password hint; may be empty
|
||||
recoverPassword recovery_code:string new_password:string new_hint:string = PasswordState;
|
||||
|
||||
//@description Removes 2-step verification password without previous password and access to recovery email address. The password can't be reset immediately and the request needs to be repeated after the specified time
|
||||
resetPassword = ResetPasswordResult;
|
||||
|
||||
//@description Cancels reset of 2-step verification password. The method can be called if passwordState.pending_reset_date > 0
|
||||
cancelPasswordReset = Ok;
|
||||
|
||||
//@description Creates a new temporary password for processing payments @password Persistent user password @valid_for Time during which the temporary password will be valid, in seconds; should be between 60 and 86400
|
||||
createTemporaryPassword password:string valid_for:int32 = TemporaryPasswordState;
|
||||
|
@ -366,6 +366,7 @@ updateChatParticipant#f3b3781f flags:# chat_id:int date:int actor_id:int user_id
|
||||
updateChannelParticipant#7fecb1ec flags:# channel_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
|
||||
updateBotStopped#7f9488a user_id:int date:int stopped:Bool qts:int = Update;
|
||||
updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJSON = Update;
|
||||
updateBotCommands#cf7e0873 peer:Peer bot_id:int commands:Vector<BotCommand> = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@ -524,7 +525,7 @@ authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true pa
|
||||
|
||||
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
|
||||
|
||||
account.password#ad2641f8 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
|
||||
account.password#185b184f flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int = account.Password;
|
||||
|
||||
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
|
||||
|
||||
@ -1250,6 +1251,10 @@ botCommandScopePeer#db9d897d peer:InputPeer = BotCommandScope;
|
||||
botCommandScopePeerAdmins#3fd863d1 peer:InputPeer = BotCommandScope;
|
||||
botCommandScopePeerUser#a1321f3 peer:InputPeer user_id:InputUser = BotCommandScope;
|
||||
|
||||
account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -1271,13 +1276,14 @@ auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int en
|
||||
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
|
||||
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
|
||||
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
|
||||
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
|
||||
auth.recoverPassword#37096c70 flags:# code:string new_settings:flags.0?account.PasswordInputSettings = auth.Authorization;
|
||||
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
|
||||
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
|
||||
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
|
||||
auth.exportLoginToken#b1b41517 api_id:int api_hash:string except_ids:Vector<int> = auth.LoginToken;
|
||||
auth.importLoginToken#95ac5ce4 token:bytes = auth.LoginToken;
|
||||
auth.acceptLoginToken#e894ad4d token:bytes = Authorization;
|
||||
auth.checkRecoveryPassword#d36bf79 code:string = Bool;
|
||||
|
||||
account.registerDevice#68976c6f flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
|
||||
account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
|
||||
@ -1347,6 +1353,8 @@ account.getMultiWallPapers#65ad71dc wallpapers:Vector<InputWallPaper> = Vector<W
|
||||
account.getGlobalPrivacySettings#eb2b4cf6 = GlobalPrivacySettings;
|
||||
account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = GlobalPrivacySettings;
|
||||
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
|
||||
account.resetPassword#9308ce1b = account.ResetPasswordResult;
|
||||
account.declinePasswordReset#4c9409f6 = Bool;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
|
@ -128,7 +128,7 @@ struct NoCryptoHeader {
|
||||
#endif
|
||||
#pragma pack(pop)
|
||||
|
||||
// mtproto v1.0
|
||||
// MTProto v1.0
|
||||
template <class HeaderT>
|
||||
std::pair<uint32, UInt128> Transport::calc_message_ack_and_key(const HeaderT &head, size_t data_size) {
|
||||
Slice part(head.encrypt_begin(), head.data + data_size);
|
||||
@ -144,7 +144,7 @@ size_t Transport::calc_crypto_size(size_t data_size) {
|
||||
return raw_size + ((enc_size + data_size + 15) & ~15);
|
||||
}
|
||||
|
||||
// mtproto v2.0
|
||||
// MTProto v2.0
|
||||
std::pair<uint32, UInt128> Transport::calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt) {
|
||||
// msg_key_large = SHA256 (substr (auth_key, 88+x, 32) + plaintext + random_padding);
|
||||
Sha256State state;
|
||||
@ -207,7 +207,7 @@ size_t Transport::calc_no_crypto_size(size_t data_size) {
|
||||
|
||||
Status Transport::read_no_crypto(MutableSlice message, PacketInfo *info, MutableSlice *data) {
|
||||
if (message.size() < sizeof(NoCryptoHeader)) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: too small [message.size() = " << message.size()
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: too small [message.size() = " << message.size()
|
||||
<< "] < [sizeof(NoCryptoHeader) = " << sizeof(NoCryptoHeader) << "]");
|
||||
}
|
||||
size_t data_size = message.size() - sizeof(NoCryptoHeader);
|
||||
@ -220,7 +220,7 @@ template <class HeaderT, class PrefixT>
|
||||
Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &auth_key, HeaderT **header_ptr,
|
||||
PrefixT **prefix_ptr, MutableSlice *data, PacketInfo *info) {
|
||||
if (message.size() < sizeof(HeaderT)) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: too small [message.size() = " << message.size()
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: too small [message.size() = " << message.size()
|
||||
<< "] < [sizeof(HeaderT) = " << sizeof(HeaderT) << "]");
|
||||
}
|
||||
//FIXME: rewrite without reinterpret cast
|
||||
@ -230,7 +230,7 @@ Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &a
|
||||
to_decrypt.remove_suffix(to_decrypt.size() & 15);
|
||||
|
||||
if (header->auth_key_id != auth_key.id()) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: auth_key_id mismatch [found = "
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: auth_key_id mismatch [found = "
|
||||
<< format::as_hex(header->auth_key_id)
|
||||
<< "] [expected = " << format::as_hex(auth_key.id()) << "]");
|
||||
}
|
||||
@ -272,31 +272,31 @@ Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &a
|
||||
}
|
||||
|
||||
if (!is_key_ok) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: message_key mismatch [found = "
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: message_key mismatch [found = "
|
||||
<< format::as_hex_dump(header->message_key)
|
||||
<< "] [expected = " << format::as_hex_dump(real_message_key) << "]");
|
||||
}
|
||||
|
||||
if (info->version == 2) {
|
||||
if (info->check_mod4 && prefix->message_data_length % 4 != 0) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (not divisible by four)"
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (not divisible by four)"
|
||||
<< tag("total_size", message.size())
|
||||
<< tag("message_data_length", prefix->message_data_length));
|
||||
}
|
||||
if (tail_size - sizeof(PrefixT) < prefix->message_data_length) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (message_data_length is too big)"
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (message_data_length is too big)"
|
||||
<< tag("total_size", message.size())
|
||||
<< tag("message_data_length", prefix->message_data_length));
|
||||
}
|
||||
size_t pad_size = tail_size - data_size;
|
||||
if (pad_size < 12 || pad_size > 1024) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (invalid padding length)"
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (invalid padding length)"
|
||||
<< tag("padding_size", pad_size) << tag("total_size", message.size())
|
||||
<< tag("message_data_length", prefix->message_data_length));
|
||||
}
|
||||
} else {
|
||||
if (!is_length_ok) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length " << tag("total_size", message.size())
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: invalid length " << tag("total_size", message.size())
|
||||
<< tag("message_data_length", prefix->message_data_length));
|
||||
}
|
||||
}
|
||||
@ -428,7 +428,7 @@ size_t Transport::write_e2e_crypto(const Storer &storer, const AuthKey &auth_key
|
||||
|
||||
Result<uint64> Transport::read_auth_key_id(Slice message) {
|
||||
if (message.size() < 8) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: smaller than 8 bytes [size = " << message.size() << "]");
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: smaller than 8 bytes [size = " << message.size() << "]");
|
||||
}
|
||||
return as<uint64>(message.begin());
|
||||
}
|
||||
@ -436,7 +436,7 @@ Result<uint64> Transport::read_auth_key_id(Slice message) {
|
||||
Result<Transport::ReadResult> Transport::read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) {
|
||||
if (message.size() < 12) {
|
||||
if (message.size() < 4) {
|
||||
return Status::Error(PSLICE() << "Invalid mtproto message: smaller than 4 bytes [size = " << message.size()
|
||||
return Status::Error(PSLICE() << "Invalid MTProto message: smaller than 4 bytes [size = " << message.size()
|
||||
<< "]");
|
||||
}
|
||||
|
||||
@ -459,7 +459,7 @@ Result<Transport::ReadResult> Transport::read(MutableSlice message, const AuthKe
|
||||
TRY_STATUS(read_no_crypto(message, info, &data));
|
||||
} else {
|
||||
if (auth_key.empty()) {
|
||||
return Status::Error("Failed to decrypt mtproto message: auth key is empty");
|
||||
return Status::Error("Failed to decrypt MTProto message: auth key is empty");
|
||||
}
|
||||
TRY_STATUS(read_crypto(message, auth_key, info, &data));
|
||||
}
|
||||
|
@ -80,10 +80,10 @@ class Transport {
|
||||
|
||||
static Result<uint64> read_auth_key_id(Slice message);
|
||||
|
||||
// Reads mtproto packet from [message] and saves into [data].
|
||||
// Reads MTProto packet from [message] and saves it into [data].
|
||||
// If message is encrypted, [auth_key] is used.
|
||||
// Decryption and unpacking is made inplace, so [data] will be subslice of [message].
|
||||
// Returns size of mtproto packet.
|
||||
// Returns size of MTProto packet.
|
||||
// If dest.size() >= size, the packet is also written into [dest].
|
||||
// If auth_key is nonempty, encryption will be used.
|
||||
static Result<ReadResult> read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) TD_WARN_UNUSED_RESULT;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/net/DcId.h"
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
#include "td/telegram/NewPasswordState.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/PasswordManager.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
@ -311,6 +312,9 @@ void AuthManager::check_password(uint64 query_id, string password) {
|
||||
LOG(INFO) << "Have SRP ID " << wait_password_state_.srp_id_;
|
||||
on_new_query(query_id);
|
||||
password_ = std::move(password);
|
||||
recovery_code_.clear();
|
||||
new_password_.clear();
|
||||
new_hint_.clear();
|
||||
start_net_query(NetQueryType::GetPassword,
|
||||
G()->net_query_creator().create_unauth(telegram_api::account_getPassword()));
|
||||
}
|
||||
@ -325,14 +329,33 @@ void AuthManager::request_password_recovery(uint64 query_id) {
|
||||
G()->net_query_creator().create_unauth(telegram_api::auth_requestPasswordRecovery()));
|
||||
}
|
||||
|
||||
void AuthManager::recover_password(uint64 query_id, string code) {
|
||||
void AuthManager::check_password_recovery_code(uint64 query_id, string code) {
|
||||
if (state_ != State::WaitPassword) {
|
||||
return on_query_error(query_id, Status::Error(8, "Call to checkAuthenticationPasswordRecoveryCode unexpected"));
|
||||
}
|
||||
|
||||
on_new_query(query_id);
|
||||
start_net_query(NetQueryType::CheckPasswordRecoveryCode,
|
||||
G()->net_query_creator().create_unauth(telegram_api::auth_checkRecoveryPassword(code)));
|
||||
}
|
||||
|
||||
void AuthManager::recover_password(uint64 query_id, string code, string new_password, string new_hint) {
|
||||
if (state_ != State::WaitPassword) {
|
||||
return on_query_error(query_id, Status::Error(8, "Call to recoverAuthenticationPassword unexpected"));
|
||||
}
|
||||
|
||||
on_new_query(query_id);
|
||||
if (!new_password.empty()) {
|
||||
password_.clear();
|
||||
recovery_code_ = std::move(code);
|
||||
new_password_ = std::move(new_password);
|
||||
new_hint_ = std::move(new_hint);
|
||||
start_net_query(NetQueryType::GetPassword,
|
||||
G()->net_query_creator().create_unauth(telegram_api::account_getPassword()));
|
||||
return;
|
||||
}
|
||||
start_net_query(NetQueryType::RecoverPassword,
|
||||
G()->net_query_creator().create_unauth(telegram_api::auth_recoverPassword(code)));
|
||||
G()->net_query_creator().create_unauth(telegram_api::auth_recoverPassword(0, code, nullptr)));
|
||||
}
|
||||
|
||||
void AuthManager::log_out(uint64 query_id) {
|
||||
@ -531,6 +554,7 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
|
||||
LOG(INFO) << "Receive password info: " << to_string(password);
|
||||
|
||||
wait_password_state_ = WaitPasswordState();
|
||||
Result<NewPasswordState> r_new_password_state;
|
||||
if (password != nullptr && password->current_algo_ != nullptr) {
|
||||
switch (password->current_algo_->get_id()) {
|
||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||
@ -552,6 +576,9 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
r_new_password_state =
|
||||
get_new_password_state(std::move(password->new_algo_), std::move(password->new_secure_algo_));
|
||||
} else if (was_qr_code_request_) {
|
||||
imported_dc_id_ = -1;
|
||||
login_code_retry_delay_ = clamp(2 * login_code_retry_delay_, 1, 60);
|
||||
@ -570,6 +597,23 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
|
||||
}
|
||||
|
||||
if (state_ == State::WaitPassword) {
|
||||
if (!new_password_.empty()) {
|
||||
if (r_new_password_state.is_error()) {
|
||||
return on_query_error(r_new_password_state.move_as_error());
|
||||
}
|
||||
|
||||
auto r_new_settings = PasswordManager::get_password_input_settings(std::move(new_password_), std::move(new_hint_),
|
||||
r_new_password_state.ok());
|
||||
if (r_new_settings.is_error()) {
|
||||
return on_query_error(r_new_settings.move_as_error());
|
||||
}
|
||||
|
||||
int32 flags = telegram_api::auth_recoverPassword::NEW_SETTINGS_MASK;
|
||||
start_net_query(NetQueryType::RecoverPassword,
|
||||
G()->net_query_creator().create_unauth(
|
||||
telegram_api::auth_recoverPassword(flags, recovery_code_, r_new_settings.move_as_ok())));
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Have SRP ID " << wait_password_state_.srp_id_;
|
||||
auto hash = PasswordManager::get_input_check_password(password_, wait_password_state_.current_client_salt_,
|
||||
wait_password_state_.current_server_salt_,
|
||||
@ -598,6 +642,17 @@ void AuthManager::on_request_password_recovery_result(NetQueryPtr &result) {
|
||||
on_query_ok();
|
||||
}
|
||||
|
||||
void AuthManager::on_check_password_recovery_code_result(NetQueryPtr &result) {
|
||||
auto r_success = fetch_result<telegram_api::auth_checkRecoveryPassword>(result->ok());
|
||||
if (r_success.is_error()) {
|
||||
return on_query_error(r_success.move_as_error());
|
||||
}
|
||||
if (!r_success.ok()) {
|
||||
return on_query_error(Status::Error(400, "Invalid recovery code"));
|
||||
}
|
||||
on_query_ok();
|
||||
}
|
||||
|
||||
void AuthManager::on_authentication_result(NetQueryPtr &result, bool is_from_current_query) {
|
||||
auto r_sign_in = fetch_result<telegram_api::auth_signIn>(result->ok());
|
||||
if (r_sign_in.is_error()) {
|
||||
@ -706,6 +761,9 @@ void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authoriz
|
||||
G()->td_db()->get_binlog_pmc()->set("auth", "ok");
|
||||
code_.clear();
|
||||
password_.clear();
|
||||
recovery_code_.clear();
|
||||
new_password_.clear();
|
||||
new_hint_.clear();
|
||||
state_ = State::Ok;
|
||||
td->contacts_manager_->on_get_user(std::move(auth->user_), "on_get_authorization", true);
|
||||
update_state(State::Ok, true);
|
||||
@ -818,6 +876,9 @@ void AuthManager::on_result(NetQueryPtr result) {
|
||||
case NetQueryType::RequestPasswordRecovery:
|
||||
on_request_password_recovery_result(result);
|
||||
break;
|
||||
case NetQueryType::CheckPasswordRecoveryCode:
|
||||
on_check_password_recovery_code_result(result);
|
||||
break;
|
||||
case NetQueryType::LogOut:
|
||||
on_log_out_result(result);
|
||||
break;
|
||||
|
@ -42,7 +42,8 @@ class AuthManager : public NetActor {
|
||||
void check_bot_token(uint64 query_id, string bot_token);
|
||||
void check_password(uint64 query_id, string password);
|
||||
void request_password_recovery(uint64 query_id);
|
||||
void recover_password(uint64 query_id, string code);
|
||||
void check_password_recovery_code(uint64 query_id, string code);
|
||||
void recover_password(uint64 query_id, string code, string new_password, string new_hint);
|
||||
void log_out(uint64 query_id);
|
||||
void delete_account(uint64 query_id, const string &reason);
|
||||
|
||||
@ -79,6 +80,7 @@ class AuthManager : public NetActor {
|
||||
GetPassword,
|
||||
CheckPassword,
|
||||
RequestPasswordRecovery,
|
||||
CheckPasswordRecoveryCode,
|
||||
RecoverPassword,
|
||||
BotAuthentication,
|
||||
Authentication,
|
||||
@ -197,6 +199,10 @@ class AuthManager : public NetActor {
|
||||
|
||||
WaitPasswordState wait_password_state_;
|
||||
|
||||
string recovery_code_;
|
||||
string new_password_;
|
||||
string new_hint_;
|
||||
|
||||
int32 login_code_retry_delay_ = 0;
|
||||
Timeout poll_export_login_code_timeout_;
|
||||
|
||||
@ -225,6 +231,7 @@ class AuthManager : public NetActor {
|
||||
void on_request_qr_code_result(NetQueryPtr &result, bool is_import);
|
||||
void on_get_password_result(NetQueryPtr &result);
|
||||
void on_request_password_recovery_result(NetQueryPtr &result);
|
||||
void on_check_password_recovery_code_result(NetQueryPtr &result);
|
||||
void on_authentication_result(NetQueryPtr &result, bool expected_flag);
|
||||
void on_log_out_result(NetQueryPtr &result);
|
||||
void on_delete_account_result(NetQueryPtr &result);
|
||||
|
@ -6057,6 +6057,90 @@ void ContactsManager::update_is_location_visible() {
|
||||
G()->shared_config().set_option_boolean("is_location_visible", expire_date != 0);
|
||||
}
|
||||
|
||||
void ContactsManager::on_update_bot_commands(DialogId dialog_id, UserId bot_user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands) {
|
||||
if (!bot_user_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive updateBotCOmmands about invalid " << bot_user_id;
|
||||
return;
|
||||
}
|
||||
if (!have_user(bot_user_id) || !is_user_bot(bot_user_id)) {
|
||||
return;
|
||||
}
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto is_from_bot = [bot_user_id](const BotCommands &commands) {
|
||||
return commands.get_bot_user_id() == bot_user_id;
|
||||
};
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User: {
|
||||
UserId user_id(dialog_id.get_user_id());
|
||||
auto user_full = get_user_full(user_id);
|
||||
if (user_full != nullptr) {
|
||||
on_update_user_full_commands(user_full, user_id, std::move(bot_commands));
|
||||
update_user_full(user_full, user_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::Chat: {
|
||||
ChatId chat_id(dialog_id.get_chat_id());
|
||||
auto chat_full = get_chat_full(chat_id);
|
||||
if (chat_full != nullptr) {
|
||||
if (bot_commands.empty()) {
|
||||
if (td::remove_if(chat_full->bot_commands, is_from_bot)) {
|
||||
chat_full->is_changed = true;
|
||||
}
|
||||
} else {
|
||||
BotCommands commands(bot_user_id, std::move(bot_commands));
|
||||
auto it = std::find_if(chat_full->bot_commands.begin(), chat_full->bot_commands.end(), is_from_bot);
|
||||
if (it != chat_full->bot_commands.end()) {
|
||||
if (*it != commands) {
|
||||
*it = std::move(commands);
|
||||
chat_full->is_changed = true;
|
||||
}
|
||||
} else {
|
||||
chat_full->bot_commands.push_back(std::move(commands));
|
||||
chat_full->is_changed = true;
|
||||
}
|
||||
}
|
||||
update_chat_full(chat_full, chat_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::Channel: {
|
||||
ChannelId channel_id(dialog_id.get_channel_id());
|
||||
auto channel_full = get_channel_full(channel_id, "on_update_bot_commands");
|
||||
if (channel_full != nullptr) {
|
||||
if (bot_commands.empty()) {
|
||||
if (td::remove_if(channel_full->bot_commands, is_from_bot)) {
|
||||
channel_full->is_changed = true;
|
||||
}
|
||||
} else {
|
||||
BotCommands commands(bot_user_id, std::move(bot_commands));
|
||||
auto it = std::find_if(channel_full->bot_commands.begin(), channel_full->bot_commands.end(), is_from_bot);
|
||||
if (it != channel_full->bot_commands.end()) {
|
||||
if (*it != commands) {
|
||||
*it = std::move(commands);
|
||||
channel_full->is_changed = true;
|
||||
}
|
||||
} else {
|
||||
channel_full->bot_commands.push_back(std::move(commands));
|
||||
channel_full->is_changed = true;
|
||||
}
|
||||
}
|
||||
update_channel_full(channel_full, channel_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::SecretChat:
|
||||
default:
|
||||
LOG(ERROR) << "Receive updateBotCommands in " << dialog_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FileId ContactsManager::get_profile_photo_file_id(int64 photo_id) const {
|
||||
auto it = my_photo_file_id_.find(photo_id);
|
||||
if (it == my_photo_file_id_.end()) {
|
||||
@ -10080,9 +10164,7 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
|
||||
if (user->bot_info_ != nullptr && !td_->auth_manager_->is_bot()) {
|
||||
description = std::move(user->bot_info_->description_);
|
||||
|
||||
auto commands = transform(std::move(user->bot_info_->commands_),
|
||||
[](auto &&bot_command) { return BotCommand(std::move(bot_command)); });
|
||||
on_update_user_full_commands(user_full, user_id, std::move(commands));
|
||||
on_update_user_full_commands(user_full, user_id, std::move(user->bot_info_->commands_));
|
||||
}
|
||||
if (user_full->description != description) {
|
||||
user_full->description = std::move(description);
|
||||
@ -11011,8 +11093,11 @@ void ContactsManager::on_update_user_full_common_chat_count(UserFull *user_full,
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsManager::on_update_user_full_commands(UserFull *user_full, UserId user_id, vector<BotCommand> &&commands) {
|
||||
void ContactsManager::on_update_user_full_commands(UserFull *user_full, UserId user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands) {
|
||||
CHECK(user_full != nullptr);
|
||||
auto commands =
|
||||
transform(std::move(bot_commands), [](auto &&bot_command) { return BotCommand(std::move(bot_command)); });
|
||||
if (user_full->commands != commands) {
|
||||
user_full->commands = std::move(commands);
|
||||
user_full->is_changed = true;
|
||||
|
@ -210,6 +210,9 @@ class ContactsManager : public Actor {
|
||||
|
||||
int32 on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers, bool from_update);
|
||||
|
||||
void on_update_bot_commands(DialogId dialog_id, UserId bot_user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
|
||||
void on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
|
||||
bool have_access, bool from_database);
|
||||
|
||||
@ -1184,7 +1187,8 @@ class ContactsManager : public Actor {
|
||||
|
||||
void on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked);
|
||||
void on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id, int32 common_chat_count);
|
||||
void on_update_user_full_commands(UserFull *user_full, UserId user_id, vector<BotCommand> &&commands);
|
||||
void on_update_user_full_commands(UserFull *user_full, UserId user_id,
|
||||
vector<tl_object_ptr<telegram_api::botCommand>> &&bot_commands);
|
||||
void on_update_user_full_need_phone_number_privacy_exception(UserFull *user_full, UserId user_id,
|
||||
bool need_phone_number_privacy_exception);
|
||||
|
||||
|
59
td/telegram/NewPasswordState.cpp
Normal file
59
td/telegram/NewPasswordState.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// 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/NewPasswordState.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
Result<NewPasswordState> get_new_password_state(
|
||||
tl_object_ptr<telegram_api::PasswordKdfAlgo> new_algo,
|
||||
tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> new_secure_algo) {
|
||||
NewPasswordState state;
|
||||
CHECK(new_algo != nullptr);
|
||||
switch (new_algo->get_id()) {
|
||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||
return Status::Error(400, "Please update client to continue");
|
||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||
auto algo =
|
||||
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(new_algo);
|
||||
state.client_salt = algo->salt1_.as_slice().str();
|
||||
state.server_salt = algo->salt2_.as_slice().str();
|
||||
state.srp_g = algo->g_;
|
||||
state.srp_p = algo->p_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CHECK(new_secure_algo != nullptr);
|
||||
switch (new_secure_algo->get_id()) {
|
||||
case telegram_api::securePasswordKdfAlgoUnknown::ID:
|
||||
return Status::Error(400, "Please update client to continue");
|
||||
case telegram_api::securePasswordKdfAlgoSHA512::ID:
|
||||
return Status::Error(500, "Server has sent outdated secret encryption mode");
|
||||
case telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000::ID: {
|
||||
auto algo = move_tl_object_as<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(new_secure_algo);
|
||||
state.secure_salt = algo->salt_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static constexpr size_t MIN_NEW_SECURE_SALT_SIZE = 8;
|
||||
if (state.secure_salt.size() < MIN_NEW_SECURE_SALT_SIZE) {
|
||||
return Status::Error(500, "New secure salt length too small");
|
||||
}
|
||||
|
||||
static constexpr size_t MIN_NEW_SALT_SIZE = 8;
|
||||
if (state.client_salt.size() < MIN_NEW_SALT_SIZE) {
|
||||
return Status::Error(500, "New salt length too small");
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
} // namespace td
|
28
td/telegram/NewPasswordState.h
Normal file
28
td/telegram/NewPasswordState.h
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
struct NewPasswordState {
|
||||
string client_salt;
|
||||
string server_salt;
|
||||
string srp_p;
|
||||
string secure_salt;
|
||||
int32 srp_g = 0;
|
||||
};
|
||||
|
||||
Result<NewPasswordState> get_new_password_state(
|
||||
tl_object_ptr<telegram_api::PasswordKdfAlgo> new_algo,
|
||||
tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> new_secure_algo);
|
||||
|
||||
} // namespace td
|
@ -465,7 +465,7 @@ void PasswordManager::check_email_address_verification_code(string code, Promise
|
||||
|
||||
void PasswordManager::request_password_recovery(
|
||||
Promise<td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise) {
|
||||
// is called only after authoriation
|
||||
// is called only after authorization
|
||||
send_with_promise(
|
||||
G()->net_query_creator().create(telegram_api::auth_requestPasswordRecovery()),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
@ -478,9 +478,55 @@ void PasswordManager::request_password_recovery(
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::recover_password(string code, Promise<State> promise) {
|
||||
// is called only after authoriation
|
||||
send_with_promise(G()->net_query_creator().create(telegram_api::auth_recoverPassword(std::move(code))),
|
||||
void PasswordManager::check_password_recovery_code(string code, Promise<Unit> promise) {
|
||||
// is called only after authorization
|
||||
send_with_promise(G()->net_query_creator().create(telegram_api::auth_checkRecoveryPassword(code)),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
auto r_result = fetch_result<telegram_api::auth_checkRecoveryPassword>(std::move(r_query));
|
||||
if (r_result.is_error()) {
|
||||
return promise.set_error(r_result.move_as_error());
|
||||
}
|
||||
if (!r_result.ok()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid recovery code"));
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::recover_password(string code, string new_password, string new_hint, Promise<State> promise) {
|
||||
// is called only after authorization
|
||||
if (new_password.empty()) {
|
||||
return do_recover_password(std::move(code), nullptr, std::move(promise));
|
||||
}
|
||||
|
||||
UpdateSettings update_settings;
|
||||
update_settings.update_password = true;
|
||||
update_settings.new_password = std::move(new_password);
|
||||
update_settings.new_hint = std::move(new_hint);
|
||||
|
||||
do_get_state(PromiseCreator::lambda([actor_id = actor_id(this), code = std::move(code),
|
||||
update_settings = std::move(update_settings),
|
||||
promise = std::move(promise)](Result<PasswordState> r_state) mutable {
|
||||
if (r_state.is_error()) {
|
||||
return promise.set_error(r_state.move_as_error());
|
||||
}
|
||||
|
||||
TRY_RESULT_PROMISE(
|
||||
promise, new_settings,
|
||||
get_password_input_settings(update_settings, r_state.ok().has_password, r_state.ok().new_state, nullptr));
|
||||
|
||||
send_closure(actor_id, &PasswordManager::do_recover_password, std::move(code), std::move(new_settings),
|
||||
std::move(promise));
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::do_recover_password(string code, PasswordInputSettings &&new_settings, Promise<State> &&promise) {
|
||||
int32 flags = 0;
|
||||
if (new_settings != nullptr) {
|
||||
flags |= telegram_api::auth_recoverPassword::NEW_SETTINGS_MASK;
|
||||
}
|
||||
send_with_promise(G()->net_query_creator().create(
|
||||
telegram_api::auth_recoverPassword(flags, std::move(code), std::move(new_settings))),
|
||||
PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
auto r_result = fetch_result<telegram_api::auth_recoverPassword>(std::move(r_query));
|
||||
@ -491,6 +537,44 @@ void PasswordManager::recover_password(string code, Promise<State> promise) {
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::reset_password(Promise<ResetPasswordResult> promise) {
|
||||
send_with_promise(
|
||||
G()->net_query_creator().create(telegram_api::account_resetPassword()),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
auto r_result = fetch_result<telegram_api::account_resetPassword>(std::move(r_query));
|
||||
if (r_result.is_error()) {
|
||||
return promise.set_error(r_result.move_as_error());
|
||||
}
|
||||
auto result_ptr = r_result.move_as_ok();
|
||||
switch (result_ptr->get_id()) {
|
||||
case telegram_api::account_resetPasswordOk::ID:
|
||||
return promise.set_value(td_api::make_object<td_api::resetPasswordResultOk>());
|
||||
case telegram_api::account_resetPasswordRequestedWait::ID: {
|
||||
auto result = move_tl_object_as<telegram_api::account_resetPasswordRequestedWait>(result_ptr);
|
||||
return promise.set_value(td_api::make_object<td_api::resetPasswordResultPending>(result->until_date_));
|
||||
}
|
||||
case telegram_api::account_resetPasswordFailedWait::ID: {
|
||||
auto result = move_tl_object_as<telegram_api::account_resetPasswordFailedWait>(result_ptr);
|
||||
return promise.set_value(td_api::make_object<td_api::resetPasswordResultDeclined>(result->retry_date_));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::cancel_password_reset(Promise<Unit> promise) {
|
||||
send_with_promise(G()->net_query_creator().create(telegram_api::account_declinePasswordReset()),
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
|
||||
auto r_result = fetch_result<telegram_api::account_declinePasswordReset>(std::move(r_query));
|
||||
if (r_result.is_error() && r_result.error().message() != "RESET_REQUEST_MISSING") {
|
||||
return promise.set_error(r_result.move_as_error());
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::update_password_settings(UpdateSettings update_settings, Promise<State> promise) {
|
||||
auto result_promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), promise = std::move(promise)](Result<bool> r_update_settings) mutable {
|
||||
@ -538,61 +622,80 @@ void PasswordManager::do_update_password_settings(UpdateSettings update_settings
|
||||
}));
|
||||
}
|
||||
|
||||
void PasswordManager::do_update_password_settings_impl(UpdateSettings update_settings, PasswordState state,
|
||||
PasswordPrivateState private_state, Promise<bool> promise) {
|
||||
auto new_settings = make_tl_object<telegram_api::account_passwordInputSettings>();
|
||||
Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_input_settings(
|
||||
string new_password, string new_hint, const NewPasswordState &state) {
|
||||
UpdateSettings update_settings;
|
||||
update_settings.update_password = true;
|
||||
update_settings.new_password = std::move(new_password);
|
||||
update_settings.new_hint = std::move(new_hint);
|
||||
|
||||
return get_password_input_settings(update_settings, true, state, nullptr);
|
||||
}
|
||||
|
||||
Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_input_settings(
|
||||
const UpdateSettings &update_settings, bool has_password, const NewPasswordState &state,
|
||||
const PasswordPrivateState *private_state) {
|
||||
auto settings = make_tl_object<telegram_api::account_passwordInputSettings>();
|
||||
bool have_secret = private_state != nullptr && private_state->secret;
|
||||
auto update_secure_secret = update_settings.update_secure_secret;
|
||||
if (update_settings.update_password) {
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_PASSWORD_HASH_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_ALGO_MASK;
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::HINT_MASK;
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_PASSWORD_HASH_MASK;
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_ALGO_MASK;
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::HINT_MASK;
|
||||
if (!update_settings.new_password.empty()) {
|
||||
auto new_client_salt = create_salt(state.new_client_salt);
|
||||
auto new_client_salt = create_salt(state.client_salt);
|
||||
|
||||
auto new_hash = calc_password_srp_hash(update_settings.new_password, new_client_salt.as_slice(),
|
||||
state.new_server_salt, state.new_srp_g, state.new_srp_p);
|
||||
state.server_salt, state.srp_g, state.srp_p);
|
||||
if (new_hash.is_error()) {
|
||||
return promise.set_error(Status::Error(400, "Unable to change password, because it may be unsafe"));
|
||||
return Status::Error(400, "Unable to change password, because it may be unsafe");
|
||||
}
|
||||
new_settings->new_password_hash_ = new_hash.move_as_ok();
|
||||
new_settings->new_algo_ =
|
||||
settings->new_password_hash_ = new_hash.move_as_ok();
|
||||
settings->new_algo_ =
|
||||
make_tl_object<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||
std::move(new_client_salt), BufferSlice(state.new_server_salt), state.new_srp_g,
|
||||
BufferSlice(state.new_srp_p));
|
||||
new_settings->hint_ = std::move(update_settings.new_hint);
|
||||
if (private_state.secret) {
|
||||
update_settings.update_secure_secret = true;
|
||||
std::move(new_client_salt), BufferSlice(state.server_salt), state.srp_g, BufferSlice(state.srp_p));
|
||||
settings->hint_ = std::move(update_settings.new_hint);
|
||||
if (have_secret) {
|
||||
update_secure_secret = true;
|
||||
}
|
||||
} else {
|
||||
new_settings->new_algo_ = make_tl_object<telegram_api::passwordKdfAlgoUnknown>();
|
||||
settings->new_algo_ = make_tl_object<telegram_api::passwordKdfAlgoUnknown>();
|
||||
}
|
||||
}
|
||||
|
||||
// Has no password and not setting one.
|
||||
if (!update_settings.update_password && !state.has_password) {
|
||||
update_settings.update_secure_secret = false;
|
||||
// have no password and not setting one
|
||||
if (!update_settings.update_password && !has_password) {
|
||||
update_secure_secret = false;
|
||||
}
|
||||
|
||||
// Setting an empty password
|
||||
// setting an empty password
|
||||
if (update_settings.update_password && update_settings.new_password.empty()) {
|
||||
update_settings.update_secure_secret = false;
|
||||
update_secure_secret = false;
|
||||
}
|
||||
|
||||
if (update_settings.update_secure_secret) {
|
||||
auto secret = private_state.secret ? std::move(private_state.secret.value()) : secure_storage::Secret::create_new();
|
||||
auto algorithm = make_tl_object<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(
|
||||
create_salt(state.new_secure_salt));
|
||||
if (update_secure_secret) {
|
||||
auto secret = have_secret ? std::move(private_state->secret.value()) : secure_storage::Secret::create_new();
|
||||
auto algorithm =
|
||||
make_tl_object<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(create_salt(state.secure_salt));
|
||||
auto encrypted_secret = secret.encrypt(
|
||||
update_settings.update_password ? update_settings.new_password : update_settings.current_password,
|
||||
algorithm->salt_.as_slice(), secure_storage::EnryptionAlgorithm::Pbkdf2);
|
||||
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SECURE_SETTINGS_MASK;
|
||||
new_settings->new_secure_settings_ = make_tl_object<telegram_api::secureSecretSettings>(
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_SECURE_SETTINGS_MASK;
|
||||
settings->new_secure_settings_ = make_tl_object<telegram_api::secureSecretSettings>(
|
||||
std::move(algorithm), BufferSlice(encrypted_secret.as_slice()), secret.get_hash());
|
||||
}
|
||||
if (update_settings.update_recovery_email_address) {
|
||||
new_settings->flags_ |= telegram_api::account_passwordInputSettings::EMAIL_MASK;
|
||||
new_settings->email_ = std::move(update_settings.recovery_email_address);
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::EMAIL_MASK;
|
||||
settings->email_ = std::move(update_settings.recovery_email_address);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
void PasswordManager::do_update_password_settings_impl(UpdateSettings update_settings, PasswordState state,
|
||||
PasswordPrivateState private_state, Promise<bool> promise) {
|
||||
TRY_RESULT_PROMISE(promise, new_settings,
|
||||
get_password_input_settings(update_settings, state.has_password, state.new_state, &private_state));
|
||||
auto current_hash = get_input_check_password(state.has_password ? update_settings.current_password : Slice(), state);
|
||||
auto query = G()->net_query_creator().create(
|
||||
telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings)));
|
||||
@ -681,46 +784,15 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
||||
state.unconfirmed_recovery_email_address_pattern = std::move(password->email_unconfirmed_pattern_);
|
||||
state.code_length = code_length;
|
||||
|
||||
CHECK(password->new_algo_ != nullptr);
|
||||
switch (password->new_algo_->get_id()) {
|
||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||
auto algo =
|
||||
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||
password->new_algo_);
|
||||
state.new_client_salt = algo->salt1_.as_slice().str();
|
||||
state.new_server_salt = algo->salt2_.as_slice().str();
|
||||
state.new_srp_g = algo->g_;
|
||||
state.new_srp_p = algo->p_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
if (password->flags_ & telegram_api::account_password::PENDING_RESET_DATE_MASK) {
|
||||
state.pending_reset_date = td::max(password->pending_reset_date_, 0);
|
||||
}
|
||||
|
||||
CHECK(password->new_secure_algo_ != nullptr);
|
||||
switch (password->new_secure_algo_->get_id()) {
|
||||
case telegram_api::securePasswordKdfAlgoUnknown::ID:
|
||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||
case telegram_api::securePasswordKdfAlgoSHA512::ID:
|
||||
return promise.set_error(Status::Error(500, "Server has sent outdated secret encryption mode"));
|
||||
case telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000::ID: {
|
||||
auto algo = move_tl_object_as<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(
|
||||
password->new_secure_algo_);
|
||||
state.new_secure_salt = algo->salt_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
auto &new_state = state.new_state;
|
||||
TRY_RESULT_PROMISE_ASSIGN(
|
||||
promise, new_state,
|
||||
get_new_password_state(std::move(password->new_algo_), std::move(password->new_secure_algo_)));
|
||||
|
||||
if (state.new_secure_salt.size() < MIN_NEW_SECURE_SALT_SIZE) {
|
||||
return promise.set_error(Status::Error(500, "New secure salt length too small"));
|
||||
}
|
||||
if (state.new_client_salt.size() < MIN_NEW_SALT_SIZE) {
|
||||
return promise.set_error(Status::Error(500, "New salt length too small"));
|
||||
}
|
||||
promise.set_value(std::move(state));
|
||||
}));
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/NewPasswordState.h"
|
||||
#include "td/telegram/SecureStorage.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
@ -52,6 +53,8 @@ class PasswordManager : public NetQueryCallback {
|
||||
public:
|
||||
using State = tl_object_ptr<td_api::passwordState>;
|
||||
using TempState = tl_object_ptr<td_api::temporaryPasswordState>;
|
||||
using ResetPasswordResult = tl_object_ptr<td_api::ResetPasswordResult>;
|
||||
using PasswordInputSettings = tl_object_ptr<telegram_api::account_passwordInputSettings>;
|
||||
|
||||
explicit PasswordManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
}
|
||||
@ -60,6 +63,9 @@ class PasswordManager : public NetQueryCallback {
|
||||
Slice server_salt, int32 g,
|
||||
Slice p, Slice B, int64 id);
|
||||
|
||||
static Result<PasswordInputSettings> get_password_input_settings(string new_password, string new_hint,
|
||||
const NewPasswordState &state);
|
||||
|
||||
void get_state(Promise<State> promise);
|
||||
void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address,
|
||||
string recovery_email_address, Promise<State> promise);
|
||||
@ -75,7 +81,11 @@ class PasswordManager : public NetQueryCallback {
|
||||
void check_email_address_verification_code(string code, Promise<Unit> promise);
|
||||
|
||||
void request_password_recovery(Promise<td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise);
|
||||
void recover_password(string code, Promise<State> promise);
|
||||
void check_password_recovery_code(string code, Promise<Unit> promise);
|
||||
void recover_password(string code, string new_password, string new_hint, Promise<State> promise);
|
||||
|
||||
void reset_password(Promise<ResetPasswordResult> promise);
|
||||
void cancel_password_reset(Promise<Unit> promise);
|
||||
|
||||
void get_secure_secret(string password, Promise<secure_storage::Secret> promise);
|
||||
void get_input_check_password_srp(string password,
|
||||
@ -89,9 +99,6 @@ class PasswordManager : public NetQueryCallback {
|
||||
static TempPasswordState get_temp_password_state_sync();
|
||||
|
||||
private:
|
||||
static constexpr size_t MIN_NEW_SALT_SIZE = 8;
|
||||
static constexpr size_t MIN_NEW_SECURE_SALT_SIZE = 8;
|
||||
|
||||
ActorShared<> parent_;
|
||||
|
||||
struct PasswordState {
|
||||
@ -101,6 +108,7 @@ class PasswordManager : public NetQueryCallback {
|
||||
bool has_secure_values = false;
|
||||
string unconfirmed_recovery_email_address_pattern;
|
||||
int32 code_length = 0;
|
||||
int32 pending_reset_date = 0;
|
||||
|
||||
string current_client_salt;
|
||||
string current_server_salt;
|
||||
@ -108,12 +116,8 @@ class PasswordManager : public NetQueryCallback {
|
||||
string current_srp_p;
|
||||
string current_srp_B;
|
||||
int64 current_srp_id;
|
||||
string new_client_salt;
|
||||
string new_server_salt;
|
||||
int32 new_srp_g;
|
||||
string new_srp_p;
|
||||
|
||||
string new_secure_salt;
|
||||
NewPasswordState new_state;
|
||||
|
||||
State get_password_state_object() const {
|
||||
td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo> code_info;
|
||||
@ -122,7 +126,7 @@ class PasswordManager : public NetQueryCallback {
|
||||
unconfirmed_recovery_email_address_pattern, code_length);
|
||||
}
|
||||
return td_api::make_object<td_api::passwordState>(has_password, password_hint, has_recovery_email_address,
|
||||
has_secure_values, std::move(code_info));
|
||||
has_secure_values, std::move(code_info), pending_reset_date);
|
||||
}
|
||||
};
|
||||
|
||||
@ -170,6 +174,12 @@ class PasswordManager : public NetQueryCallback {
|
||||
static tl_object_ptr<telegram_api::InputCheckPasswordSRP> get_input_check_password(Slice password,
|
||||
const PasswordState &state);
|
||||
|
||||
static Result<PasswordInputSettings> get_password_input_settings(const UpdateSettings &update_settings,
|
||||
bool has_password, const NewPasswordState &state,
|
||||
const PasswordPrivateState *private_state);
|
||||
|
||||
void do_recover_password(string code, PasswordInputSettings &&new_settings, Promise<State> &&promise);
|
||||
|
||||
void update_password_settings(UpdateSettings update_settings, Promise<State> promise);
|
||||
void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise<bool> promise);
|
||||
void do_update_password_settings_impl(UpdateSettings update_settings, PasswordState state,
|
||||
|
@ -780,12 +780,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
|
||||
<< tag("crc", crc64(encrypted_message.as_slice())));
|
||||
}
|
||||
|
||||
// expect that message is encrypted with mtproto 2.0 if their layer is at least MTPROTO_2_LAYER
|
||||
std::array<int, 2> versions{{1, 2}};
|
||||
if (config_state_.his_layer >= MTPROTO_2_LAYER) {
|
||||
std::swap(versions[0], versions[1]);
|
||||
}
|
||||
|
||||
std::array<int, 2> versions{{2, 1}};
|
||||
BufferSlice encrypted_message_copy;
|
||||
int32 mtproto_version = -1;
|
||||
Result<mtproto::Transport::ReadResult> r_read_result;
|
||||
@ -800,7 +795,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
|
||||
info.version = mtproto_version;
|
||||
info.is_creator = auth_state_.x == 0;
|
||||
r_read_result = mtproto::Transport::read(data, *auth_key, &info);
|
||||
if (i + 1 == versions.size() && r_read_result.is_error()) {
|
||||
if (i + 1 != versions.size() && r_read_result.is_error()) {
|
||||
LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error();
|
||||
continue;
|
||||
}
|
||||
@ -850,7 +845,7 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<log_event::Inbou
|
||||
parser.fetch_end();
|
||||
if (!parser.get_error()) {
|
||||
auto layer = message_with_layer->layer_;
|
||||
if (layer < DEFAULT_LAYER && false /* Android app can send such messages */) {
|
||||
if (layer < DEFAULT_LAYER && false /* old Android app could send such messages */) {
|
||||
LOG(ERROR) << "Layer " << layer << " is not supported, drop message " << to_string(message_with_layer);
|
||||
return Status::OK();
|
||||
}
|
||||
|
@ -3223,6 +3223,7 @@ bool Td::is_authentication_request(int32 id) {
|
||||
case td_api::requestQrCodeAuthentication::ID:
|
||||
case td_api::checkAuthenticationPassword::ID:
|
||||
case td_api::requestAuthenticationPasswordRecovery::ID:
|
||||
case td_api::checkAuthenticationPasswordRecoveryCode::ID:
|
||||
case td_api::recoverAuthenticationPassword::ID:
|
||||
case td_api::deleteAccount::ID:
|
||||
case td_api::logOut::ID:
|
||||
@ -4816,9 +4817,17 @@ void Td::on_request(uint64 id, const td_api::requestAuthenticationPasswordRecove
|
||||
send_closure(auth_manager_actor_, &AuthManager::request_password_recovery, id);
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::checkAuthenticationPasswordRecoveryCode &request) {
|
||||
CLEAN_INPUT_STRING(request.recovery_code_);
|
||||
send_closure(auth_manager_actor_, &AuthManager::check_password_recovery_code, id, std::move(request.recovery_code_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::recoverAuthenticationPassword &request) {
|
||||
CLEAN_INPUT_STRING(request.recovery_code_);
|
||||
send_closure(auth_manager_actor_, &AuthManager::recover_password, id, std::move(request.recovery_code_));
|
||||
CLEAN_INPUT_STRING(request.new_password_);
|
||||
CLEAN_INPUT_STRING(request.new_hint_);
|
||||
send_closure(auth_manager_actor_, &AuthManager::recover_password, id, std::move(request.recovery_code_),
|
||||
std::move(request.new_password_), std::move(request.new_hint_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::logOut &request) {
|
||||
@ -4958,12 +4967,34 @@ void Td::on_request(uint64 id, td_api::requestPasswordRecovery &request) {
|
||||
send_closure(password_manager_, &PasswordManager::request_password_recovery, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::checkPasswordRecoveryCode &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.recovery_code_);
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
send_closure(password_manager_, &PasswordManager::check_password_recovery_code, std::move(request.recovery_code_),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::recoverPassword &request) {
|
||||
CHECK_IS_USER();
|
||||
CLEAN_INPUT_STRING(request.recovery_code_);
|
||||
CLEAN_INPUT_STRING(request.new_password_);
|
||||
CLEAN_INPUT_STRING(request.new_hint_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
send_closure(password_manager_, &PasswordManager::recover_password, std::move(request.recovery_code_),
|
||||
std::move(promise));
|
||||
std::move(request.new_password_), std::move(request.new_hint_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::resetPassword &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
send_closure(password_manager_, &PasswordManager::reset_password, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::cancelPasswordReset &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
send_closure(password_manager_, &PasswordManager::cancel_password_reset, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::getTemporaryPasswordState &request) {
|
||||
|
@ -248,7 +248,7 @@ class Td final : public NetQueryCallback {
|
||||
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
||||
|
||||
private:
|
||||
static constexpr const char *TDLIB_VERSION = "1.7.4";
|
||||
static constexpr const char *TDLIB_VERSION = "1.7.5";
|
||||
static constexpr int64 ONLINE_ALARM_ID = 0;
|
||||
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
||||
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
||||
@ -418,6 +418,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, const td_api::requestAuthenticationPasswordRecovery &request);
|
||||
|
||||
void on_request(uint64 id, td_api::checkAuthenticationPasswordRecoveryCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::recoverAuthenticationPassword &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::logOut &request);
|
||||
@ -446,8 +448,14 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, td_api::requestPasswordRecovery &request);
|
||||
|
||||
void on_request(uint64 id, td_api::checkPasswordRecoveryCode &request);
|
||||
|
||||
void on_request(uint64 id, td_api::recoverPassword &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::resetPassword &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::cancelPasswordReset &request);
|
||||
|
||||
void on_request(uint64 id, td_api::getTemporaryPasswordState &request);
|
||||
|
||||
void on_request(uint64 id, td_api::createTemporaryPassword &request);
|
||||
|
@ -2613,6 +2613,12 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePeerBlocked> up
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateBotCommands> update, Promise<Unit> &&promise) {
|
||||
td_->contacts_manager_->on_update_bot_commands(DialogId(update->peer_), UserId(update->bot_id_),
|
||||
std::move(update->commands_));
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatParticipants> update, Promise<Unit> &&promise) {
|
||||
td_->contacts_manager_->on_get_chat_participants(std::move(update->participants_), true);
|
||||
promise.set_value(Unit());
|
||||
|
@ -361,6 +361,7 @@ class UpdatesManager : public Actor {
|
||||
void on_update(tl_object_ptr<telegram_api::updateUserPhoto> update, Promise<Unit> &&promise);
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updatePeerBlocked> update, Promise<Unit> &&promise);
|
||||
void on_update(tl_object_ptr<telegram_api::updateBotCommands> update, Promise<Unit> &&promise);
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateChatParticipants> update, Promise<Unit> &&promise);
|
||||
void on_update(tl_object_ptr<telegram_api::updateChatParticipantAdd> update, Promise<Unit> &&promise);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
constexpr int32 MTPROTO_LAYER = 130;
|
||||
constexpr int32 MTPROTO_LAYER = 131;
|
||||
|
||||
enum class Version : int32 {
|
||||
Initial, // 0
|
||||
|
@ -1415,11 +1415,15 @@ void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) {
|
||||
if (it != web_page_messages_.end()) {
|
||||
vector<FullMessageId> full_message_ids;
|
||||
for (auto full_message_id : it->second) {
|
||||
full_message_ids.push_back(full_message_id);
|
||||
if (full_message_id.get_dialog_id().get_type() != DialogType::SecretChat) {
|
||||
full_message_ids.push_back(full_message_id);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::get_messages_from_server, std::move(full_message_ids),
|
||||
Promise<Unit>(), nullptr);
|
||||
if (!full_message_ids.empty()) {
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::get_messages_from_server,
|
||||
std::move(full_message_ids), Promise<Unit>(), nullptr);
|
||||
}
|
||||
}
|
||||
auto get_it = pending_get_web_pages_.find(web_page_id);
|
||||
if (get_it != pending_get_web_pages_.end()) {
|
||||
|
@ -1655,8 +1655,15 @@ class CliClient final : public Actor {
|
||||
send_request(td_api::make_object<td_api::getCurrentState>());
|
||||
} else if (op == "rapr") {
|
||||
send_request(td_api::make_object<td_api::requestAuthenticationPasswordRecovery>());
|
||||
} else if (op == "caprc") {
|
||||
string recovery_code = args;
|
||||
send_request(td_api::make_object<td_api::checkAuthenticationPasswordRecoveryCode>(recovery_code));
|
||||
} else if (op == "rap") {
|
||||
send_request(td_api::make_object<td_api::recoverAuthenticationPassword>(args));
|
||||
string recovery_code;
|
||||
string new_password;
|
||||
string new_hint;
|
||||
get_args(args, recovery_code, new_password, new_hint);
|
||||
send_request(td_api::make_object<td_api::recoverAuthenticationPassword>(recovery_code, new_password, new_hint));
|
||||
} else if (op == "lo" || op == "LogOut" || op == "logout") {
|
||||
send_request(td_api::make_object<td_api::logOut>());
|
||||
} else if (op == "destroy") {
|
||||
@ -1775,10 +1782,21 @@ class CliClient final : public Actor {
|
||||
send_request(td_api::make_object<td_api::checkPhoneNumberVerificationCode>(args));
|
||||
} else if (op == "rpncc") {
|
||||
send_request(td_api::make_object<td_api::resendPhoneNumberVerificationCode>());
|
||||
} else if (op == "rpr" || op == "RequestPasswordRecovery") {
|
||||
} else if (op == "rpr") {
|
||||
send_request(td_api::make_object<td_api::requestPasswordRecovery>());
|
||||
} else if (op == "rp" || op == "RecoverPassword") {
|
||||
send_request(td_api::make_object<td_api::recoverPassword>(args));
|
||||
} else if (op == "cprc") {
|
||||
string recovery_code = args;
|
||||
send_request(td_api::make_object<td_api::checkPasswordRecoveryCode>(recovery_code));
|
||||
} else if (op == "rp") {
|
||||
string recovery_code;
|
||||
string new_password;
|
||||
string new_hint;
|
||||
get_args(args, recovery_code, new_password, new_hint);
|
||||
send_request(td_api::make_object<td_api::recoverPassword>(recovery_code, new_password, new_hint));
|
||||
} else if (op == "resetp") {
|
||||
send_request(td_api::make_object<td_api::resetPassword>());
|
||||
} else if (op == "cpr") {
|
||||
send_request(td_api::make_object<td_api::cancelPasswordReset>());
|
||||
} else if (op == "gtp" || op == "GetTemporaryPassword") {
|
||||
send_request(td_api::make_object<td_api::getTemporaryPasswordState>());
|
||||
} else if (op == "ctp" || op == "CreateTemporaryPassword") {
|
||||
|
Loading…
Reference in New Issue
Block a user