diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/example/cpp')
4 files changed, 173 insertions, 121 deletions
diff --git a/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt b/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt index 3e7794d4fa..6ad8be44b7 100644 --- a/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt +++ b/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt @@ -1,8 +1,8 @@ -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.4 FATAL_ERROR) project(TdExample VERSION 1.0 LANGUAGES CXX) -find_package(Td 1.2.0 REQUIRED) +find_package(Td 1.8.8 REQUIRED) add_executable(tdjson_example tdjson_example.cpp) target_link_libraries(tdjson_example PRIVATE Td::TdJson) diff --git a/protocols/Telegram/tdlib/td/example/cpp/README.md b/protocols/Telegram/tdlib/td/example/cpp/README.md index 9e5de531ba..1658ade6fc 100644 --- a/protocols/Telegram/tdlib/td/example/cpp/README.md +++ b/protocols/Telegram/tdlib/td/example/cpp/README.md @@ -1,4 +1,4 @@ -# TDLib cpp basic usage examples +# TDLib C++ basic usage examples TDLib should be prebuilt and installed to local subdirectory `td/`: ``` @@ -21,4 +21,4 @@ cmake --build . Documentation for all available classes and methods can be found at https://core.telegram.org/tdlib/docs. -To run `tdjson_example` you may need to manually copy a `tdjson` shared library from `td/bin` to a directory containing built binaries. +To run the examples you may need to manually copy needed shared libraries from `td/bin` to a directory containing built binaries. diff --git a/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp b/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp index 1efbf465b9..3b6cf42edc 100644 --- a/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp +++ b/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp @@ -1,19 +1,18 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // 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/Client.h> -#include <td/telegram/Log.h> #include <td/telegram/td_api.h> #include <td/telegram/td_api.hpp> #include <cstdint> #include <functional> #include <iostream> -#include <limits> #include <map> +#include <memory> #include <sstream> #include <string> #include <vector> @@ -35,7 +34,7 @@ struct overload<F> : public F { template <class F, class... Fs> struct overload<F, Fs...> : public overload<F> - , overload<Fs...> { + , public overload<Fs...> { overload(F f, Fs... fs) : overload<F>(f), overload<Fs...>(fs...) { } using overload<F>::operator(); @@ -53,8 +52,10 @@ namespace td_api = td::td_api; class TdExample { public: TdExample() { - td::Log::set_verbosity_level(1); - client_ = std::make_unique<td::Client>(); + td::ClientManager::execute(td_api::make_object<td_api::setLogVerbosityLevel>(1)); + client_manager_ = std::make_unique<td::ClientManager>(); + client_id_ = client_manager_->create_client_id(); + send_query(td_api::make_object<td_api::getOption>("version"), {}); } void loop() { @@ -62,10 +63,10 @@ class TdExample { if (need_restart_) { restart(); } else if (!are_authorized_) { - process_response(client_->receive(10)); + process_response(client_manager_->receive(10)); } else { - std::cerr << "Enter action [q] quit [u] check for updates and request results [c] show chats [m <id> <text>] " - "send message [l] logout: " + std::cout << "Enter action [q] quit [u] check for updates and request results [c] show chats [m <chat_id> " + "<text>] send message [me] show self [l] logout: " << std::endl; std::string line; std::getline(std::cin, line); @@ -78,17 +79,23 @@ class TdExample { return; } if (action == "u") { - std::cerr << "Checking for updates..." << std::endl; + std::cout << "Checking for updates..." << std::endl; while (true) { - auto response = client_->receive(0); + auto response = client_manager_->receive(0); if (response.object) { process_response(std::move(response)); } else { break; } } + } else if (action == "close") { + std::cout << "Closing..." << std::endl; + send_query(td_api::make_object<td_api::close>(), {}); + } else if (action == "me") { + send_query(td_api::make_object<td_api::getMe>(), + [this](Object object) { std::cout << to_string(object) << std::endl; }); } else if (action == "l") { - std::cerr << "Logging out..." << std::endl; + std::cout << "Logging out..." << std::endl; send_query(td_api::make_object<td_api::logOut>(), {}); } else if (action == "m") { std::int64_t chat_id; @@ -97,7 +104,7 @@ class TdExample { std::string text; std::getline(ss, text); - std::cerr << "Sending message to chat " << chat_id << "..." << std::endl; + std::cout << "Sending message to chat " << chat_id << "..." << std::endl; auto send_message = td_api::make_object<td_api::sendMessage>(); send_message->chat_id_ = chat_id; auto message_content = td_api::make_object<td_api::inputMessageText>(); @@ -107,17 +114,16 @@ class TdExample { send_query(std::move(send_message), {}); } else if (action == "c") { - std::cerr << "Loading chat list..." << std::endl; - send_query(td_api::make_object<td_api::getChats>(std::numeric_limits<std::int64_t>::max(), 0, 20), - [this](Object object) { - if (object->get_id() == td_api::error::ID) { - return; - } - auto chats = td::move_tl_object_as<td_api::chats>(object); - for (auto chat_id : chats->chat_ids_) { - std::cerr << "[id:" << chat_id << "] [title:" << chat_title_[chat_id] << "]" << std::endl; - } - }); + std::cout << "Loading chat list..." << std::endl; + send_query(td_api::make_object<td_api::getChats>(nullptr, 20), [this](Object object) { + if (object->get_id() == td_api::error::ID) { + return; + } + auto chats = td::move_tl_object_as<td_api::chats>(object); + for (auto chat_id : chats->chat_ids_) { + std::cout << "[chat_id:" << chat_id << "] [title:" << chat_title_[chat_id] << "]" << std::endl; + } + }); } } } @@ -125,7 +131,8 @@ class TdExample { private: using Object = td_api::object_ptr<td_api::Object>; - std::unique_ptr<td::Client> client_; + std::unique_ptr<td::ClientManager> client_manager_; + std::int32_t client_id_{0}; td_api::object_ptr<td_api::AuthorizationState> authorization_state_; bool are_authorized_{false}; @@ -135,12 +142,12 @@ class TdExample { std::map<std::uint64_t, std::function<void(Object)>> handlers_; - std::map<std::int32_t, td_api::object_ptr<td_api::user>> users_; + std::map<std::int64_t, td_api::object_ptr<td_api::user>> users_; std::map<std::int64_t, std::string> chat_title_; void restart() { - client_.reset(); + client_manager_.reset(); *this = TdExample(); } @@ -149,24 +156,25 @@ class TdExample { if (handler) { handlers_.emplace(query_id, std::move(handler)); } - client_->send({query_id, std::move(f)}); + client_manager_->send(client_id_, query_id, std::move(f)); } - void process_response(td::Client::Response response) { + void process_response(td::ClientManager::Response response) { if (!response.object) { return; } - //std::cerr << response.id << " " << to_string(response.object) << std::endl; - if (response.id == 0) { + //std::cout << response.request_id << " " << to_string(response.object) << std::endl; + if (response.request_id == 0) { return process_update(std::move(response.object)); } - auto it = handlers_.find(response.id); + auto it = handlers_.find(response.request_id); if (it != handlers_.end()) { it->second(std::move(response.object)); + handlers_.erase(it); } } - std::string get_user_name(std::int32_t user_id) { + std::string get_user_name(std::int64_t user_id) const { auto it = users_.find(user_id); if (it == users_.end()) { return "unknown user"; @@ -174,6 +182,14 @@ class TdExample { return it->second->first_name_ + " " + it->second->last_name_; } + std::string get_chat_title(std::int64_t chat_id) const { + auto it = chat_title_.find(chat_id); + if (it == chat_title_.end()) { + return "unknown chat"; + } + return it->second; + } + void process_update(td_api::object_ptr<td_api::Object> update) { td_api::downcast_call( *update, overloaded( @@ -193,13 +209,21 @@ class TdExample { }, [this](td_api::updateNewMessage &update_new_message) { auto chat_id = update_new_message.message_->chat_id_; - auto sender_user_name = get_user_name(update_new_message.message_->sender_user_id_); + std::string sender_name; + td_api::downcast_call(*update_new_message.message_->sender_id_, + overloaded( + [this, &sender_name](td_api::messageSenderUser &user) { + sender_name = get_user_name(user.user_id_); + }, + [this, &sender_name](td_api::messageSenderChat &chat) { + sender_name = get_chat_title(chat.chat_id_); + })); std::string text; if (update_new_message.message_->content_->get_id() == td_api::messageText::ID) { text = static_cast<td_api::messageText &>(*update_new_message.message_->content_).text_->text_; } - std::cerr << "Got message: [chat_id:" << chat_id << "] [from:" << sender_user_name << "] [" - << text << "]" << std::endl; + std::cout << "Got message: [chat_id:" << chat_id << "] [from:" << sender_name << "] [" << text + << "]" << std::endl; }, [](auto &update) {})); } @@ -214,85 +238,91 @@ class TdExample { void on_authorization_state_update() { authentication_query_id_++; - td_api::downcast_call( - *authorization_state_, - overloaded( - [this](td_api::authorizationStateReady &) { - are_authorized_ = true; - std::cerr << "Got authorization" << std::endl; - }, - [this](td_api::authorizationStateLoggingOut &) { - are_authorized_ = false; - std::cerr << "Logging out" << std::endl; - }, - [this](td_api::authorizationStateClosing &) { std::cerr << "Closing" << std::endl; }, - [this](td_api::authorizationStateClosed &) { - are_authorized_ = false; - need_restart_ = true; - std::cerr << "Terminated" << std::endl; - }, - [this](td_api::authorizationStateWaitCode &wait_code) { - std::string first_name; - std::string last_name; - if (!wait_code.is_registered_) { - std::cerr << "Enter your first name: "; - std::cin >> first_name; - std::cerr << "Enter your last name: "; - std::cin >> last_name; - } - std::cerr << "Enter authentication code: "; - std::string code; - std::cin >> code; - send_query(td_api::make_object<td_api::checkAuthenticationCode>(code, first_name, last_name), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitPassword &) { - std::cerr << "Enter authentication password: "; - std::string password; - std::cin >> password; - send_query(td_api::make_object<td_api::checkAuthenticationPassword>(password), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitPhoneNumber &) { - std::cerr << "Enter phone number: "; - std::string phone_number; - std::cin >> phone_number; - send_query(td_api::make_object<td_api::setAuthenticationPhoneNumber>( - phone_number, false /*allow_flash_calls*/, false /*is_current_phone_number*/), - create_authentication_query_handler()); - }, - [this](td_api::authorizationStateWaitEncryptionKey &) { - std::cerr << "Enter encryption key or DESTROY: "; - std::string key; - std::getline(std::cin, key); - if (key == "DESTROY") { - send_query(td_api::make_object<td_api::destroy>(), create_authentication_query_handler()); - } else { - send_query(td_api::make_object<td_api::checkDatabaseEncryptionKey>(std::move(key)), - create_authentication_query_handler()); - } - }, - [this](td_api::authorizationStateWaitTdlibParameters &) { - auto parameters = td_api::make_object<td_api::tdlibParameters>(); - parameters->database_directory_ = "tdlib"; - parameters->use_message_database_ = true; - parameters->use_secret_chats_ = true; - parameters->api_id_ = 94575; - parameters->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; - parameters->system_language_code_ = "en"; - parameters->device_model_ = "Desktop"; - parameters->system_version_ = "Unknown"; - parameters->application_version_ = "1.0"; - parameters->enable_storage_optimizer_ = true; - send_query(td_api::make_object<td_api::setTdlibParameters>(std::move(parameters)), - create_authentication_query_handler()); - })); + td_api::downcast_call(*authorization_state_, + overloaded( + [this](td_api::authorizationStateReady &) { + are_authorized_ = true; + std::cout << "Got authorization" << std::endl; + }, + [this](td_api::authorizationStateLoggingOut &) { + are_authorized_ = false; + std::cout << "Logging out" << std::endl; + }, + [this](td_api::authorizationStateClosing &) { std::cout << "Closing" << std::endl; }, + [this](td_api::authorizationStateClosed &) { + are_authorized_ = false; + need_restart_ = true; + std::cout << "Terminated" << std::endl; + }, + [this](td_api::authorizationStateWaitPhoneNumber &) { + std::cout << "Enter phone number: " << std::flush; + std::string phone_number; + std::cin >> phone_number; + send_query( + td_api::make_object<td_api::setAuthenticationPhoneNumber>(phone_number, nullptr), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitEmailAddress &) { + std::cout << "Enter email address: " << std::flush; + std::string email_address; + std::cin >> email_address; + send_query(td_api::make_object<td_api::setAuthenticationEmailAddress>(email_address), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitEmailCode &) { + std::cout << "Enter email authentication code: " << std::flush; + std::string code; + std::cin >> code; + send_query(td_api::make_object<td_api::checkAuthenticationEmailCode>( + td_api::make_object<td_api::emailAddressAuthenticationCode>(code)), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitCode &) { + std::cout << "Enter authentication code: " << std::flush; + std::string code; + std::cin >> code; + send_query(td_api::make_object<td_api::checkAuthenticationCode>(code), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitRegistration &) { + std::string first_name; + std::string last_name; + std::cout << "Enter your first name: " << std::flush; + std::cin >> first_name; + std::cout << "Enter your last name: " << std::flush; + std::cin >> last_name; + send_query(td_api::make_object<td_api::registerUser>(first_name, last_name), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitPassword &) { + std::cout << "Enter authentication password: " << std::flush; + std::string password; + std::getline(std::cin, password); + send_query(td_api::make_object<td_api::checkAuthenticationPassword>(password), + create_authentication_query_handler()); + }, + [this](td_api::authorizationStateWaitOtherDeviceConfirmation &state) { + std::cout << "Confirm this login link on another device: " << state.link_ << std::endl; + }, + [this](td_api::authorizationStateWaitTdlibParameters &) { + auto request = td_api::make_object<td_api::setTdlibParameters>(); + request->database_directory_ = "tdlib"; + request->use_message_database_ = true; + request->use_secret_chats_ = true; + request->api_id_ = 94575; + request->api_hash_ = "a3406de8d171bb422bb6ddf3bbd800e2"; + request->system_language_code_ = "en"; + request->device_model_ = "Desktop"; + request->application_version_ = "1.0"; + request->enable_storage_optimizer_ = true; + send_query(std::move(request), create_authentication_query_handler()); + })); } void check_authentication_error(Object object) { if (object->get_id() == td_api::error::ID) { auto error = td::move_tl_object_as<td_api::error>(object); - std::cerr << "Error: " << to_string(error); + std::cout << "Error: " << to_string(error) << std::flush; on_authorization_state_update(); } } diff --git a/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp b/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp index 6787b37f86..dcf203f2e9 100644 --- a/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp +++ b/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // 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) @@ -12,14 +12,38 @@ // the main event cycle, which should be essentially the same for all languages. int main() { - void *client = td_json_client_create(); - // somehow share the client with other threads, which will be able to send requests via td_json_client_send + // disable TDLib logging + td_execute("{\"@type\":\"setLogVerbosityLevel\", \"new_verbosity_level\":0}"); + + int client_id = td_create_client_id(); + // somehow share the client_id with other threads, which will be able to send requests via td_send + + // start the client by sending request to it + td_send(client_id, "{\"@type\":\"getOption\", \"name\":\"version\"}"); + + const bool test_incorrect_queries = false; + if (test_incorrect_queries) { + td_execute("{\"@type\":\"setLogVerbosityLevel\", \"new_verbosity_level\":1}"); + td_execute(""); + td_execute("test"); + td_execute("\"test\""); + td_execute("{\"@type\":\"test\", \"@extra\":1}"); + + td_send(client_id, "{\"@type\":\"getFileMimeType\"}"); + td_send(client_id, "{\"@type\":\"getFileMimeType\", \"@extra\":1}"); + td_send(client_id, "{\"@type\":\"getFileMimeType\", \"@extra\":null}"); + td_send(client_id, "{\"@type\":\"test\"}"); + td_send(client_id, "[]"); + td_send(client_id, "{\"@type\":\"test\", \"@extra\":1}"); + td_send(client_id, "{\"@type\":\"sendMessage\", \"chat_id\":true, \"@extra\":1}"); + td_send(client_id, "test"); + } const double WAIT_TIMEOUT = 10.0; // seconds while (true) { - const char *result = td_json_client_receive(client, WAIT_TIMEOUT); + const char *result = td_receive(WAIT_TIMEOUT); if (result != nullptr) { - // parse the result as JSON object and process it as an incoming update or an answer to a previously sent request + // parse the result as a JSON object and process it as an incoming update or an answer to a previously sent request // if (result is UpdateAuthorizationState with authorizationStateClosed) { // break; @@ -28,6 +52,4 @@ int main() { std::cout << result << std::endl; } } - - td_json_client_destroy(client); } |