diff --git a/CMakeLists.txt b/CMakeLists.txt index abe93c861..177972a3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -370,6 +370,7 @@ set(TDLIB_SOURCE td/telegram/Global.cpp td/telegram/HashtagHints.cpp td/telegram/InlineQueriesManager.cpp + td/telegram/LanguagePackManager.cpp td/telegram/Location.cpp td/telegram/MessageEntity.cpp td/telegram/MessagesDb.cpp @@ -483,6 +484,7 @@ set(TDLIB_SOURCE td/telegram/Global.h td/telegram/HashtagHints.h td/telegram/InlineQueriesManager.h + td/telegram/LanguagePackManager.h td/telegram/Location.h td/telegram/logevent/LogEvent.h td/telegram/logevent/LogEventHelper.h diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 483bf2c82..d78933ae3 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1652,6 +1652,29 @@ chatEvents events:vector = ChatEvents; chatEventLogFilters message_edits:Bool message_deletions:Bool message_pins:Bool member_joins:Bool member_leaves:Bool member_invites:Bool member_promotions:Bool member_restrictions:Bool info_changes:Bool setting_changes:Bool = ChatEventLogFilters; +//@class LanguagePackString @description Represents one language pack string + +//@description An ordinary language pack string @key String key @value String value +languagePackStringValue key:string value:string = LanguagePackString; + +//@description A language pack string, which has different forms based on some quantity @key String key @zero_value Value for zero objects @one_value Value for one object @two_value Value for two objects +//@few_value Value for few objects @many_value Value for many objects @other_value Default value +languagePackStringPluralized key:string zero_value:string one_value:string two_value:string few_value:string many_value:string other_value:string = LanguagePackString; + +//@description A deleted language pack string @key String key +languagePackStringDeleted key:string = LanguagePackString; + + +//@description Contains a list of language pack strings @strings A list of language pack strings +languagePackStrings strings:vector = LanguagePackStrings; + +//@description Contains information about a language @code Language code @name Language name @native_name Language native name +languageInfo code:string name:string native_name:string = LanguageInfo; + +//@description Contains information about a language pack @languages List of available languages +languagePack languages:vector = LanguagePack; + + //@class DeviceToken @description Represents a data needed to subscribe for push notifications. To use specific push notification service, you must specify the correct application platform and upload valid server authentication data at https://my.telegram.org //@description A token for Google Cloud Messaging @token Device registration token; may be empty to de-register a device @@ -3025,6 +3048,13 @@ getSupportUser = User; getWallpapers = Wallpapers; +//@description Returns information about used language pack +getLanguagePack = LanguagePack; + +//@description Returns strings from used language pack on specified language by their keys @language_code Language code of strings to return @keys Language pack keys of strings to return; may be empty to get all available strings +getLanguagePackStrings language_code:string keys:vector = LanguagePackStrings; + + //@description Registers the currently used device for receiving push notifications @device_token Device token @other_user_ids List of at most 100 user identifiers of other users currently using the client registerDevice device_token:DeviceToken other_user_ids:vector = Ok; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 120bf7cdb..b442faaa5 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/LanguagePackManager.cpp b/td/telegram/LanguagePackManager.cpp new file mode 100644 index 000000000..ce0a81567 --- /dev/null +++ b/td/telegram/LanguagePackManager.cpp @@ -0,0 +1,131 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// 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/LanguagePackManager.h" + +#include "td/telegram/Global.h" +#include "td/telegram/logevent/LogEvent.h" +#include "td/telegram/net/NetQueryDispatcher.h" + +#include "td/utils/logging.h" + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +namespace td { + +void LanguagePackManager::get_languages(Promise> promise) { + auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + + auto languages = r_result.move_as_ok(); + auto results = make_tl_object(); + results->languages_.reserve(languages.size()); + for (auto &language : languages) { + results->languages_.push_back( + make_tl_object(language->lang_code_, language->name_, language->native_name_)); + } + promise.set_value(std::move(results)); + }); + send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getLanguages())), + std::move(request_promise)); +} + +void LanguagePackManager::get_language_pack_strings(string language_code, vector keys, + Promise> promise) { + bool is_all = keys.empty(); + auto result_promise = + PromiseCreator::lambda([actor_id = actor_id(this), is_all, promise = std::move(promise)]( + Result>> r_result) mutable { + send_closure(actor_id, &LanguagePackManager::on_get_language_pack_strings, std::move(r_result), is_all, + std::move(promise)); + }); + + if (is_all) { + auto request_promise = + PromiseCreator::lambda([promise = std::move(result_promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + + auto result = r_result.move_as_ok(); + LOG(INFO) << "Receive language pack for language " << result->lang_code_ << " from version " + << result->from_version_ << " with version " << result->version_ << " of size " + << result->strings_.size(); + promise.set_value(std::move(result->strings_)); + }); + send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getLangPack(language_code))), + std::move(request_promise)); + } else { + auto request_promise = + PromiseCreator::lambda([promise = std::move(result_promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + + promise.set_value(r_result.move_as_ok()); + }); + send_with_promise(G()->net_query_creator().create( + create_storer(telegram_api::langpack_getStrings(language_code, std::move(keys)))), + std::move(request_promise)); + } +} + +void LanguagePackManager::on_get_language_pack_strings( + Result>> r_result, bool ia_all, + Promise> promise) { + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + auto result = + transform(r_result.move_as_ok(), [](const auto &string_ptr) -> tl_object_ptr { + CHECK(string_ptr != nullptr); + switch (string_ptr->get_id()) { + case telegram_api::langPackString::ID: { + auto str = static_cast(string_ptr.get()); + return make_tl_object(str->key_, str->value_); + } + case telegram_api::langPackStringPluralized::ID: { + auto str = static_cast(string_ptr.get()); + return make_tl_object(str->key_, str->zero_value_, str->one_value_, + str->two_value_, str->few_value_, + str->many_value_, str->other_value_); + } + case telegram_api::langPackStringDeleted::ID: { + auto str = static_cast(string_ptr.get()); + return make_tl_object(str->key_); + } + default: + UNREACHABLE(); + return nullptr; + } + }); + + promise.set_value(make_tl_object(std::move(result))); +} + +void LanguagePackManager::on_result(NetQueryPtr query) { + auto token = get_link_token(); + container_.extract(token).set_value(std::move(query)); +} + +void LanguagePackManager::send_with_promise(NetQueryPtr query, Promise promise) { + auto id = container_.create(std::move(promise)); + G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this, id)); +} + +void LanguagePackManager::hangup() { + container_.for_each( + [](auto id, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + stop(); +} + +} // namespace td diff --git a/td/telegram/LanguagePackManager.h b/td/telegram/LanguagePackManager.h new file mode 100644 index 000000000..4a0b9762a --- /dev/null +++ b/td/telegram/LanguagePackManager.h @@ -0,0 +1,48 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// 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/net/NetQuery.h" + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/actor/actor.h" +#include "td/actor/PromiseFuture.h" + +#include "td/utils/Container.h" + +namespace td { + +class LanguagePackManager : public NetQueryCallback { + public: + explicit LanguagePackManager(ActorShared<> parent) : parent_(std::move(parent)) { + } + + void get_languages(Promise> promise); + + void get_language_pack_strings(string language_code, vector keys, + Promise> promise); + + private: + ActorShared<> parent_; + + string language_pack_; + string language_code_; + + void on_get_language_pack_strings(Result>> r_result, bool ia_all, + Promise> promise); + + void on_result(NetQueryPtr query) override; + + void hangup() override; + + Container> container_; + void send_with_promise(NetQueryPtr query, Promise promise); +}; + +} // namespace td diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 9f65875d6..6493d61e0 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -50,13 +50,13 @@ class PasswordManager : public NetQueryCallback { explicit PasswordManager(ActorShared<> parent) : parent_(std::move(parent)) { } + void get_state(Promise promise); void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address, string recovery_email_address, Promise promise); void set_recovery_email_address(string password, string new_recovery_email_address, Promise promise); void get_recovery_email_address(string password, Promise> promise); - string last_verified_email_address_; void send_email_address_verification_code( string email, Promise> promise); void resend_email_address_verification_code( @@ -125,6 +125,8 @@ class PasswordManager : public NetQueryCallback { TempPasswordState temp_password_state_; Promise create_temp_password_promise_; + string last_verified_email_address_; + void update_password_settings(UpdateSettings update_settings, Promise promise); void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise promise); void do_get_state(Promise promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3605144c2..1b0081517 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -40,6 +40,7 @@ #include "td/telegram/Global.h" #include "td/telegram/HashtagHints.h" #include "td/telegram/InlineQueriesManager.h" +#include "td/telegram/LanguagePackManager.h" #include "td/telegram/MessageEntity.h" #include "td/telegram/MessageId.h" #include "td/telegram/MessagesManager.h" @@ -3229,6 +3230,8 @@ bool Td::is_preinitialization_request(int32 id) { bool Td::is_preauthentication_request(int32 id) { switch (id) { case td_api::processDcUpdate::ID: + case td_api::getLanguagePack::ID: + case td_api::getLanguagePackStrings::ID: case td_api::getOption::ID: case td_api::setOption::ID: case td_api::setNetworkType::ID: @@ -3758,6 +3761,8 @@ void Td::clear() { LOG(DEBUG) << "DeviceTokenManager was cleared " << timer; hashtag_hints_.reset(); LOG(DEBUG) << "HashtagHints was cleared " << timer; + language_pack_manager_.reset(); + LOG(DEBUG) << "LanguagePackManager was cleared " << timer; net_stats_manager_.reset(); LOG(DEBUG) << "NetStatsManager was cleared " << timer; password_manager_.reset(); @@ -4060,6 +4065,7 @@ Status Td::init(DbKey key) { "ConfirmPhoneNumberManager", PhoneNumberManager::Type::ConfirmPhone, create_reference()); device_token_manager_ = create_actor("DeviceTokenManager", create_reference()); hashtag_hints_ = create_actor("HashtagHints", "text", create_reference()); + language_pack_manager_ = create_actor("LanguagePackManager", create_reference()); password_manager_ = create_actor("PasswordManager", create_reference()); G()->set_password_manager(password_manager_.get()); privacy_manager_ = create_actor("PrivacyManager", create_reference()); @@ -5922,6 +5928,23 @@ void Td::on_request(uint64 id, const td_api::resetAllNotificationSettings &reque send_closure(actor_id(this), &Td::send_result, id, make_tl_object()); } +void Td::on_request(uint64 id, const td_api::getLanguagePack &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + send_closure(language_pack_manager_, &LanguagePackManager::get_languages, std::move(promise)); +} + +void Td::on_request(uint64 id, td_api::getLanguagePackStrings &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.language_code_); + for (auto &key : request.keys_) { + CLEAN_INPUT_STRING(key); + } + CREATE_REQUEST_PROMISE(); + send_closure(language_pack_manager_, &LanguagePackManager::get_language_pack_strings, + std::move(request.language_code_), std::move(request.keys_), std::move(promise)); +} + void Td::on_request(uint64 id, td_api::getOption &request) { CLEAN_INPUT_STRING(request.name_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 629f703e2..43629f232 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -45,6 +45,7 @@ class DocumentsManager; class FileManager; class InlineQueriesManager; class HashtagHints; +class LanguagePackManager; class MessagesManager; class NetStatsManager; class PasswordManager; @@ -152,6 +153,7 @@ class Td final : public NetQueryCallback { ActorOwn confirm_phone_number_manager_; ActorOwn device_token_manager_; ActorOwn hashtag_hints_; + ActorOwn language_pack_manager_; ActorOwn net_stats_manager_; ActorOwn password_manager_; ActorOwn privacy_manager_; @@ -749,6 +751,10 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::reportChat &request); + void on_request(uint64 id, const td_api::getLanguagePack &request); + + void on_request(uint64 id, td_api::getLanguagePackStrings &request); + void on_request(uint64 id, td_api::getOption &request); void on_request(uint64 id, td_api::setOption &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 635eb701e..67cad2455 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1699,6 +1699,14 @@ class CliClient final : public Actor { std::tie(chat_id, message_id) = split(args); send_request(make_tl_object(as_chat_id(chat_id), as_message_id(message_id))); + } else if (op == "glp") { + send_request(make_tl_object()); + } else if (op == "glps") { + string language_code; + string keys; + + std::tie(language_code, keys) = split(args); + send_request(make_tl_object(language_code, full_split(keys))); } else if (op == "go") { send_request(make_tl_object(args)); } else if (op == "sob") { diff --git a/tdactor/td/actor/Condition.h b/tdactor/td/actor/Condition.h index c3799df48..e5065dc97 100644 --- a/tdactor/td/actor/Condition.h +++ b/tdactor/td/actor/Condition.h @@ -11,6 +11,7 @@ #include "td/utils/logging.h" namespace td { + class Condition { class Helper : public Actor { public: @@ -44,4 +45,5 @@ class Condition { ActorId actor_; ActorOwn own_actor_; }; + } // namespace td diff --git a/tdactor/td/actor/MultiPromise.cpp b/tdactor/td/actor/MultiPromise.cpp index 0d98f5cfb..9000cfeca 100644 --- a/tdactor/td/actor/MultiPromise.cpp +++ b/tdactor/td/actor/MultiPromise.cpp @@ -7,6 +7,7 @@ #include "td/actor/MultiPromise.h" namespace td { + void MultiPromiseActor::add_promise(Promise &&promise) { promises_.emplace_back(std::move(promise)); } @@ -87,4 +88,5 @@ MultiPromiseActorSafe::~MultiPromiseActorSafe() { register_existing_actor(std::move(multi_promise_)).release(); } } + } // namespace td diff --git a/tdactor/td/actor/PromiseFuture.h b/tdactor/td/actor/PromiseFuture.h index 81af29e24..57ee33252 100644 --- a/tdactor/td/actor/PromiseFuture.h +++ b/tdactor/td/actor/PromiseFuture.h @@ -22,6 +22,7 @@ #include namespace td { + template class PromiseInterface { public: @@ -651,4 +652,5 @@ class PromiseCreator { return Promise(std::make_unique>(std::move(from))); } }; + } // namespace td diff --git a/tdactor/td/actor/SchedulerLocalStorage.h b/tdactor/td/actor/SchedulerLocalStorage.h index f505836a1..ab245a895 100644 --- a/tdactor/td/actor/SchedulerLocalStorage.h +++ b/tdactor/td/actor/SchedulerLocalStorage.h @@ -14,6 +14,7 @@ #include namespace td { + template class SchedulerLocalStorage { public: diff --git a/tdactor/td/actor/SignalSlot.h b/tdactor/td/actor/SignalSlot.h index 73b48f58e..74e46754e 100644 --- a/tdactor/td/actor/SignalSlot.h +++ b/tdactor/td/actor/SignalSlot.h @@ -9,7 +9,9 @@ #include "td/actor/actor.h" namespace td { + class Slot; + class Signal { public: void emit(); @@ -20,6 +22,7 @@ class Signal { private: ActorId slot_id_; }; + class Slot final : public Actor { public: Slot() = default; @@ -101,6 +104,7 @@ class Slot final : public Actor { signal(); } }; + inline void Signal::emit() { send_closure(slot_id_, &Slot::signal); } diff --git a/tdactor/td/actor/Timeout.h b/tdactor/td/actor/Timeout.h index a3a9ba191..11ee040da 100644 --- a/tdactor/td/actor/Timeout.h +++ b/tdactor/td/actor/Timeout.h @@ -15,6 +15,7 @@ #include namespace td { + class Timeout final : public Actor { public: using Data = void *;