diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e86122e..54d1f1a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) -project(TDLib VERSION 1.0.3 LANGUAGES CXX C) +project(TDLib VERSION 1.0.4 LANGUAGES CXX C) if (NOT DEFINED CMAKE_MODULE_PATH) set(CMAKE_MODULE_PATH "") diff --git a/README.md b/README.md index 89ddb84d..fca3420b 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ target_link_library(YourLibrary Td::TdJson) Or you could install `TDLib` and then reference it in your CMakeLists.txt like this: ``` -find_package(Td 1.0.3) +find_package(Td 1.0.4) target_link_library(YourLibrary Td::TdJson) ``` See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt). diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt index 7ee4567d..651aa620 100644 --- a/example/cpp/CMakeLists.txt +++ b/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.0.3 REQUIRED) +find_package(Td 1.0.4 REQUIRED) add_executable(tdjson_example tdjson_example.cpp) target_link_libraries(tdjson_example PRIVATE Td::TdJson) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index e7cbc7c8..a0a26229 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1419,17 +1419,30 @@ chatEventLogFilters message_edits:Bool message_deletions:Bool message_pins:Bool //@class DeviceToken @description Represents a token for push notifications -//@description A token for Apple Push Notification Service @token Token, may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled -deviceTokenApplePush token:string is_app_sandbox:Bool = DeviceToken; - -//@description A token for Google Cloud Messaging @token Token, may be empty to de-register a device +//@description A token for Google Cloud Messaging @token Device registration token, may be empty to de-register a device deviceTokenGoogleCloudMessaging token:string = DeviceToken; -//@description A token for Microsoft Push Notification Service @token Token, may be empty to de-register a device -deviceTokenMicrosoftPush token:string = DeviceToken; +//@description A token for Apple Push Notification Service @device_token Device token, may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled +deviceTokenApplePush device_token:string is_app_sandbox:Bool = DeviceToken; -//@description A token for Simple Push API @token Token, may be empty to de-register a device -deviceTokenSimplePush token:string = DeviceToken; +//@description A token for Apple Push Notification Service VoIP notifications @device_token Device token, may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled +deviceTokenApplePushVoIP device_token:string is_app_sandbox:Bool = DeviceToken; + +//@description A token for Windows Push Notification Services @access_token The access token that will be used to send notifications, may be empty to de-register a device +deviceTokenWindowsPush access_token:string = DeviceToken; + +//@description A token for Microsoft Push Notification Service @channel_uri Push notification channel URI, may be empty to de-register a device +deviceTokenMicrosoftPush channel_uri:string = DeviceToken; + +//@description A token for Microsoft Push Notification Service VoIP channel @channel_uri Push notification channel URI, may be empty to de-register a device +deviceTokenMicrosoftPushVoIP channel_uri:string = DeviceToken; + +//@description A token for web Push API @endpoint Absolute URL exposed by the push service where the application server can send push messages, may be empty to de-register a device +//@p256dh_base64url Base64url-encoded P-256 elliptic curve Diffie-Hellman public key @auth_base64url Base64url-encoded authentication secret +deviceTokenWebPush endpoint:string p256dh_base64url:string auth_base64url:string = DeviceToken; + +//@description A token for Simple Push API for Firefox OS @endpoint Absolute URL exposed by the push service where the application server can send push messages, may be empty to de-register a device +deviceTokenSimplePush endpoint:string = DeviceToken; //@description A token for Ubuntu Push Client service @token Token, may be empty to de-register a device deviceTokenUbuntuPush token:string = DeviceToken; @@ -1437,6 +1450,9 @@ deviceTokenUbuntuPush token:string = DeviceToken; //@description A token for Blackberry Push Service @token Token, may be empty to de-register a device deviceTokenBlackberryPush token:string = DeviceToken; +//@description A token for Tizen Push Service @reg_id Push service registration identifier, may be empty to de-register a device +deviceTokenTizenPush reg_id:string = DeviceToken; + //@description Contains information about a wallpaper @id Unique persistent wallpaper identifier @sizes Available variants of the wallpaper in different sizes. These photos can only be downloaded; they can't be sent in a message @color Main color of the wallpaper in RGB24 format; should be treated as background color if no photos are specified wallpaper id:int32 sizes:vector color:int32 = Wallpaper; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index d2426775..ab286810 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/DeviceTokenManager.cpp b/td/telegram/DeviceTokenManager.cpp index e4a8df0e..a0887059 100644 --- a/td/telegram/DeviceTokenManager.cpp +++ b/td/telegram/DeviceTokenManager.cpp @@ -14,10 +14,11 @@ #include "td/telegram/td_api.hpp" #include "td/telegram/telegram_api.h" +#include "td/utils/base64.h" #include "td/utils/format.h" +#include "td/utils/JsonBuilder.h" #include "td/utils/logging.h" #include "td/utils/Status.h" -#include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" #include @@ -105,7 +106,7 @@ void DeviceTokenManager::register_device(tl_object_ptr devi switch (device_token_ptr->get_id()) { case td_api::deviceTokenApplePush::ID: { auto device_token = static_cast(device_token_ptr.get()); - token = std::move(device_token->token_); + token = std::move(device_token->device_token_); token_type = TokenType::APNS; is_app_sandbox = device_token->is_app_sandbox_; break; @@ -118,31 +119,110 @@ void DeviceTokenManager::register_device(tl_object_ptr devi } case td_api::deviceTokenMicrosoftPush::ID: { auto device_token = static_cast(device_token_ptr.get()); - token = std::move(device_token->token_); + token = std::move(device_token->channel_uri_); token_type = TokenType::MPNS; break; } case td_api::deviceTokenSimplePush::ID: { auto device_token = static_cast(device_token_ptr.get()); - token = std::move(device_token->token_); - token_type = TokenType::SimplePush; + token = std::move(device_token->endpoint_); + token_type = TokenType::SIMPLE_PUSH; break; } case td_api::deviceTokenUbuntuPush::ID: { auto device_token = static_cast(device_token_ptr.get()); token = std::move(device_token->token_); - token_type = TokenType::UbuntuPhone; + token_type = TokenType::UBUNTU_PHONE; break; } case td_api::deviceTokenBlackberryPush::ID: { auto device_token = static_cast(device_token_ptr.get()); token = std::move(device_token->token_); - token_type = TokenType::Blackberry; + token_type = TokenType::BLACKBERRY; + break; + } + case td_api::deviceTokenWindowsPush::ID: { + auto device_token = static_cast(device_token_ptr.get()); + token = std::move(device_token->access_token_); + token_type = TokenType::WNS; + break; + } + case td_api::deviceTokenApplePushVoIP::ID: { + auto device_token = static_cast(device_token_ptr.get()); + token = std::move(device_token->device_token_); + token_type = TokenType::APNS_VOIP; + is_app_sandbox = device_token->is_app_sandbox_; + break; + } + case td_api::deviceTokenWebPush::ID: { + auto device_token = static_cast(device_token_ptr.get()); + if (device_token->endpoint_.find(',') != string::npos) { + return promise.set_error(Status::Error(400, "Illegal endpoint value")); + } + if (!is_base64url(device_token->p256dh_base64url_)) { + return promise.set_error(Status::Error(400, "Public key must be base64url-encoded")); + } + if (!is_base64url(device_token->auth_base64url_)) { + return promise.set_error(Status::Error(400, "Authentication secret must be base64url-encoded")); + } + if (!clean_input_string(device_token->endpoint_)) { + return promise.set_error(Status::Error(400, "Endpoint must be encoded in UTF-8")); + } + + if (!device_token->endpoint_.empty()) { + class JsonKeys : public Jsonable { + public: + JsonKeys(Slice p256dh, Slice auth) : p256dh_(p256dh), auth_(auth) { + } + void store(JsonValueScope *scope) const { + auto object = scope->enter_object(); + object << ctie("p256dh", p256dh_); + object << ctie("auth", auth_); + } + + private: + Slice p256dh_; + Slice auth_; + }; + class JsonWebPushToken : public Jsonable { + public: + JsonWebPushToken(Slice endpoint, Slice p256dh, Slice auth) + : endpoint_(endpoint), p256dh_(p256dh), auth_(auth) { + } + void store(JsonValueScope *scope) const { + auto object = scope->enter_object(); + object << ctie("endpoint", endpoint_); + object << ctie("keys", JsonKeys(p256dh_, auth_)); + } + + private: + Slice endpoint_; + Slice p256dh_; + Slice auth_; + }; + + token = json_encode( + JsonWebPushToken(device_token->endpoint_, device_token->p256dh_base64url_, device_token->auth_base64url_)); + } + token_type = TokenType::WEB_PUSH; + break; + } + case td_api::deviceTokenMicrosoftPushVoIP::ID: { + auto device_token = static_cast(device_token_ptr.get()); + token = std::move(device_token->channel_uri_); + token_type = TokenType::MPNS_VOIP; + break; + } + case td_api::deviceTokenTizenPush::ID: { + auto device_token = static_cast(device_token_ptr.get()); + token = std::move(device_token->reg_id_); + token_type = TokenType::TIZEN; break; } default: UNREACHABLE(); } + if (!clean_input_string(token)) { return promise.set_error(Status::Error(400, "Device token must be encoded in UTF-8")); } @@ -181,7 +261,7 @@ string DeviceTokenManager::get_database_key(int32 token_type) { } void DeviceTokenManager::start_up() { - for (int32 token_type = 1; token_type < TokenType::Size; token_type++) { + for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) { auto serialized = G()->td_db()->get_binlog_pmc()->get(get_database_key(token_type)); if (serialized.empty()) { continue; @@ -231,7 +311,7 @@ void DeviceTokenManager::loop() { if (sync_cnt_ != 0) { return; } - for (int32 token_type = 1; token_type < TokenType::Size; token_type++) { + for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) { auto &info = tokens_[token_type]; if (info.state == TokenInfo::State::Sync) { continue; @@ -256,7 +336,7 @@ void DeviceTokenManager::loop() { void DeviceTokenManager::on_result(NetQueryPtr net_query) { auto token_type = static_cast(get_link_token()); - CHECK(token_type >= 1 && token_type < TokenType::Size); + CHECK(token_type >= 1 && token_type < TokenType::SIZE); auto &info = tokens_[token_type]; if (info.net_query_id != net_query->id()) { net_query->clear(); diff --git a/td/telegram/DeviceTokenManager.h b/td/telegram/DeviceTokenManager.h index cf51d33c..8858f85d 100644 --- a/td/telegram/DeviceTokenManager.h +++ b/td/telegram/DeviceTokenManager.h @@ -14,6 +14,7 @@ #include "td/telegram/td_api.h" #include "td/utils/common.h" +#include "td/utils/StringBuilder.h" #include @@ -30,7 +31,21 @@ class DeviceTokenManager : public NetQueryCallback { static constexpr size_t MAX_OTHER_USER_IDS = 100; ActorShared<> parent_; - enum TokenType : int32 { APNS = 1, GCM = 2, MPNS = 3, SimplePush = 4, UbuntuPhone = 5, Blackberry = 6, Size }; + enum TokenType : int32 { + APNS = 1, + GCM = 2, + MPNS = 3, + SIMPLE_PUSH = 4, + UBUNTU_PHONE = 5, + BLACKBERRY = 6, + UNUSED = 7, + WNS = 8, + APNS_VOIP = 9, + WEB_PUSH = 10, + MPNS_VOIP = 11, + TIZEN = 12, + SIZE + }; struct TokenInfo { enum class State { Sync, Unregister, Register }; State state = State::Sync; @@ -49,7 +64,7 @@ class DeviceTokenManager : public NetQueryCallback { friend StringBuilder &operator<<(StringBuilder &string_builder, const TokenInfo &token_info); - std::array tokens_; + std::array tokens_; int32 sync_cnt_{0}; void start_up() override; diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 01e4268b..4b547af5 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -965,7 +965,8 @@ td_api::object_ptr copy(const td_api::file &obj) { if (file_id.is_valid()) { return G()->td().get_actor_unsafe()->file_manager_.get()->get_file_object(file_id); } else { - return td_api::make_object(obj.id_, obj.size_, obj.expected_size_, copy(obj.local_), copy(obj.remote_)); + return td_api::make_object(obj.id_, obj.size_, obj.expected_size_, copy(obj.local_), + copy(obj.remote_)); } } diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b8e943fe..a97cef3a 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -187,7 +187,7 @@ class Td final : public NetQueryCallback { static td_api::object_ptr static_request(td_api::object_ptr function); private: - static constexpr const char *tdlib_version = "1.0.3"; + static constexpr const char *tdlib_version = "1.0.4"; static constexpr int32 ONLINE_TIMEOUT = 240; void send_result(uint64 id, tl_object_ptr object); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 76cc91c5..5f352eed 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1027,6 +1027,13 @@ class CliClient final : public Actor { } else if (op == "rdb") { send_request(make_tl_object(make_tl_object(args), as_user_ids(""))); + } else if (op == "rdt") { + string token; + string other_user_ids_str; + + std::tie(token, other_user_ids_str) = split(args); + send_request(make_tl_object(make_tl_object(token), + as_user_ids(other_user_ids_str))); } else if (op == "rdu") { string token; string other_user_ids_str; @@ -1034,6 +1041,17 @@ class CliClient final : public Actor { std::tie(token, other_user_ids_str) = split(args); send_request(make_tl_object(make_tl_object(token), as_user_ids(other_user_ids_str))); + } else if (op == "rdw") { + string endpoint; + string key; + string secret; + string other_user_ids_str; + + std::tie(endpoint, args) = split(args); + std::tie(key, args) = split(args); + std::tie(secret, other_user_ids_str) = split(args); + send_request(make_tl_object( + make_tl_object(endpoint, key, secret), as_user_ids(other_user_ids_str))); } else if (op == "gpf") { string chat_id; string message_id;