diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e545a6f2d..6213d9bd5 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3475,6 +3475,18 @@ void Td::on_config_option_updated(const string &name) { } else if (name == "disable_top_chats") { send_closure(top_dialog_manager_, &TopDialogManager::update_is_enabled, !G()->shared_config().get_option_boolean(name)); + } else if (name == "is_emulator") { + if (G()->mtproto_header().set_is_emulator(G()->shared_config().get_option_boolean(name))) { + G()->net_query_dispatcher().update_mtproto_header(); + } + } else if (name == "language_pack") { + if (G()->mtproto_header().set_language_pack(G()->shared_config().get_option_string(name))) { + G()->net_query_dispatcher().update_mtproto_header(); + } + } else if (name == "language_code") { + if (G()->mtproto_header().set_language_code(G()->shared_config().get_option_string(name))) { + G()->net_query_dispatcher().update_mtproto_header(); + } } else if (is_internal_config_option(name)) { return; } @@ -3926,17 +3938,6 @@ Status Td::init(DbKey key) { class ConfigSharedCallback : public ConfigShared::Callback { public: void on_option_updated(const string &name, const string &value) override { - if (name == "is_emulator" && !G()->close_flag()) { - // it should be applied immediately, because it affects MtprotoHeader - if (G()->have_mtproto_header()) { - // can't use G()->shared_config(), because it may be not created yet - G()->mtproto_header().set_is_emulator(value == "Btrue"); - } - if (G()->have_net_query_dispatcher()) { - G()->net_query_dispatcher().update_mtproto_header(); - } - } - send_closure(G()->td(), &Td::on_config_option_updated, name); } }; @@ -3959,6 +3960,12 @@ Status Td::init(DbKey key) { } }); + options_.language_pack = G()->shared_config().get_option_string("language_pack"); + options_.language_code = G()->shared_config().get_option_string("language_code"); + options_.is_emulator = G()->shared_config().get_option_boolean("is_emulator"); + // options_.proxy = Proxy(); + G()->set_mtproto_header(std::make_unique(options_)); + VLOG(td_init) << "Create NetQueryDispatcher"; auto net_query_dispatcher = std::make_unique([&] { return create_reference(); }); G()->set_net_query_dispatcher(std::move(net_query_dispatcher)); @@ -4327,32 +4334,32 @@ Status Td::set_parameters(td_api::object_ptr parameters inc_request_actor_refcnt(); // guard inc_actor_refcnt(); // guard - VLOG(td_init) << "Create MtprotoHeader"; - MtprotoHeader::Options options; - options.api_id = parameters->api_id_; - options.system_language_code = trim(parameters->system_language_code_); - options.device_model = trim(parameters->device_model_); - options.system_version = trim(parameters->system_version_); - options.application_version = trim(parameters->application_version_); - if (options.system_language_code.empty()) { + VLOG(td_init) << "Create MtprotoHeader::Options"; + options_.api_id = parameters->api_id_; + options_.system_language_code = trim(parameters->system_language_code_); + options_.device_model = trim(parameters->device_model_); + options_.system_version = trim(parameters->system_version_); + options_.application_version = trim(parameters->application_version_); + if (options_.system_language_code.empty()) { return Status::Error(400, "System language code must be non-empty"); } - if (options.device_model.empty()) { + if (options_.device_model.empty()) { return Status::Error(400, "Device model must be non-empty"); } - if (options.system_version.empty()) { + if (options_.system_version.empty()) { return Status::Error(400, "System version must be non-empty"); } - if (options.application_version.empty()) { + if (options_.application_version.empty()) { return Status::Error(400, "Application version must be non-empty"); } - if (options.api_id != 21724) { - options.application_version += ", TDLib "; - options.application_version += TDLIB_VERSION; + if (options_.api_id != 21724) { + options_.application_version += ", TDLib "; + options_.application_version += TDLIB_VERSION; } - options.is_emulator = false; - options.proxy = Proxy(); - G()->set_mtproto_header(std::make_unique(options)); + options_.language_pack = ""; + options_.language_code = ""; + options_.is_emulator = false; + options_.proxy = Proxy(); state_ = State::Decrypt; VLOG(td_init) << "Send authorizationStateWaitEncryptionKey"; @@ -5963,6 +5970,25 @@ void Td::on_request(uint64 id, td_api::setOption &request) { return false; }; + auto set_string_option = [&](Slice name) { + if (request.name_ == name) { + if (value_constructor_id != td_api::optionValueString::ID && + value_constructor_id != td_api::optionValueEmpty::ID) { + send_error_raw(id, 3, PSLICE() << "Option \"" << name << "\" must have string value"); + return true; + } + if (value_constructor_id == td_api::optionValueEmpty::ID) { + G()->shared_config().set_option_empty(name); + } else { + G()->shared_config().set_option_string(name, + static_cast(request.value_.get())->value_); + } + send_closure(actor_id(this), &Td::send_result, id, make_tl_object()); + return true; + } + return false; + }; + switch (request.name_[0]) { case 'd': if (set_boolean_option("disable_contact_registered_notifications")) { @@ -5980,6 +6006,14 @@ void Td::on_request(uint64 id, td_api::setOption &request) { return; } break; + case 'l': + if (set_string_option("language_pack")) { + return; + } + if (set_string_option("language_code")) { + return; + } + break; case 'o': if (request.name_ == "online") { if (value_constructor_id != td_api::optionValueBoolean::ID && diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 94b7e97bd..629f703e2 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/net/MtprotoHeader.h" #include "td/telegram/net/NetQuery.h" #include "td/telegram/StateManager.h" #include "td/telegram/TdCallback.h" @@ -37,7 +38,6 @@ class AudiosManager; class AuthManager; class CallManager; class CallbackQueriesManager; -class PhoneNumberManager; class ConfigManager; class ContactsManager; class DeviceTokenManager; @@ -48,6 +48,7 @@ class HashtagHints; class MessagesManager; class NetStatsManager; class PasswordManager; +class PhoneNumberManager; class PrivacyManager; class SecureManager; class SecretChatsManager; @@ -223,6 +224,8 @@ class Td final : public NetQueryCallback { void dec_stop_cnt(); + MtprotoHeader::Options options_; + TdParameters parameters_; unique_ptr callback_; diff --git a/td/telegram/net/MtprotoHeader.cpp b/td/telegram/net/MtprotoHeader.cpp index d77dba3ad..7312213bf 100644 --- a/td/telegram/net/MtprotoHeader.cpp +++ b/td/telegram/net/MtprotoHeader.cpp @@ -11,6 +11,7 @@ namespace td { namespace { + class HeaderStorer { public: HeaderStorer(const MtprotoHeader::Options &options, bool is_anonymous) @@ -60,6 +61,7 @@ class HeaderStorer { const MtprotoHeader::Options &options; bool is_anonymous; }; + } // namespace string MtprotoHeader::gen_header(const MtprotoHeader::Options &options, bool is_anonymous) { diff --git a/td/telegram/net/MtprotoHeader.h b/td/telegram/net/MtprotoHeader.h index c3621337a..ebcdea8d9 100644 --- a/td/telegram/net/MtprotoHeader.h +++ b/td/telegram/net/MtprotoHeader.h @@ -20,8 +20,10 @@ class MtprotoHeader { string system_language_code; string device_model; string system_version; - bool is_emulator = false; string application_version; + string language_pack; + string language_code; + bool is_emulator = false; Proxy proxy; }; @@ -34,9 +36,34 @@ class MtprotoHeader { default_header_ = gen_header(options_, false); } - void set_is_emulator(bool is_emulator) { + bool set_is_emulator(bool is_emulator) { + if (options_.is_emulator == is_emulator) { + return false; + } + options_.is_emulator = is_emulator; default_header_ = gen_header(options_, false); + return true; + } + + bool set_language_pack(string language_pack) { + if (options_.language_pack == language_pack) { + return false; + } + + options_.language_pack = std::move(language_pack); + default_header_ = gen_header(options_, false); + return true; + } + + bool set_language_code(string language_code) { + if (options_.language_code == language_code) { + return false; + } + + options_.language_code = std::move(language_code); + default_header_ = gen_header(options_, false); + return true; } Slice get_default_header() const {