diff options
| author | aunsane <aunsane@gmail.com> | 2018-04-27 21:33:17 +0300 | 
|---|---|---|
| committer | aunsane <aunsane@gmail.com> | 2018-04-27 21:33:17 +0300 | 
| commit | e1ec72eab6d00b3ba38e5932bc88920f103b6e4a (patch) | |
| tree | 999de2725a83e30fbbf6576200525d4ef0c5fe38 /protocols/Telegram/tdlib/td/example/cpp | |
| parent | b9ce1d4d98525490ca1a38e2d9fd4f3369adb3e0 (diff) | |
Telegram: initial commit
- tdlib moved to telegram dir
Diffstat (limited to 'protocols/Telegram/tdlib/td/example/cpp')
5 files changed, 379 insertions, 0 deletions
diff --git a/protocols/Telegram/tdlib/td/example/cpp/.gitignore b/protocols/Telegram/tdlib/td/example/cpp/.gitignore new file mode 100644 index 0000000000..336dc7d458 --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/cpp/.gitignore @@ -0,0 +1 @@ +td/ diff --git a/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt b/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt new file mode 100644 index 0000000000..3e7794d4fa --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/cpp/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) + +project(TdExample VERSION 1.0 LANGUAGES CXX) + +find_package(Td 1.2.0 REQUIRED) + +add_executable(tdjson_example tdjson_example.cpp) +target_link_libraries(tdjson_example PRIVATE Td::TdJson) +set_property(TARGET tdjson_example PROPERTY CXX_STANDARD 11) + +add_executable(td_example td_example.cpp) +target_link_libraries(td_example PRIVATE Td::TdStatic) +set_property(TARGET td_example PROPERTY CXX_STANDARD 14) diff --git a/protocols/Telegram/tdlib/td/example/cpp/README.md b/protocols/Telegram/tdlib/td/example/cpp/README.md new file mode 100644 index 0000000000..9e5de531ba --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/cpp/README.md @@ -0,0 +1,24 @@ +# TDLib cpp basic usage examples + +TDLib should be prebuilt and installed to local subdirectory `td/`: +``` +cd <path to TDLib sources> +mkdir build +cd build +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../example/cpp/td .. +cmake --build . --target install +``` +Also see [building](https://github.com/tdlib/td#building) for additional details on TDLib building. + +Then you can build the examples: +``` +cd <path to TDLib sources>/example/cpp +mkdir build +cd build +cmake -DCMAKE_BUILD_TYPE=Release -DTd_DIR=<full path to TDLib sources>/example/cpp/td/lib/cmake/Td .. +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. diff --git a/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp b/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp new file mode 100644 index 0000000000..1efbf465b9 --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/cpp/td_example.cpp @@ -0,0 +1,308 @@ +// +// 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/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 <sstream> +#include <string> +#include <vector> + +// Simple single-threaded example of TDLib usage. +// Real world programs should use separate thread for the user input. +// Example includes user authentication, receiving updates, getting chat list and sending text messages. + +// overloaded +namespace detail { +template <class... Fs> +struct overload; + +template <class F> +struct overload<F> : public F { +  explicit overload(F f) : F(f) { +  } +}; +template <class F, class... Fs> +struct overload<F, Fs...> +    : public overload<F> +    , overload<Fs...> { +  overload(F f, Fs... fs) : overload<F>(f), overload<Fs...>(fs...) { +  } +  using overload<F>::operator(); +  using overload<Fs...>::operator(); +}; +}  // namespace detail + +template <class... F> +auto overloaded(F... f) { +  return detail::overload<F...>(f...); +} + +namespace td_api = td::td_api; + +class TdExample { + public: +  TdExample() { +    td::Log::set_verbosity_level(1); +    client_ = std::make_unique<td::Client>(); +  } + +  void loop() { +    while (true) { +      if (need_restart_) { +        restart(); +      } else if (!are_authorized_) { +        process_response(client_->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::endl; +        std::string line; +        std::getline(std::cin, line); +        std::istringstream ss(line); +        std::string action; +        if (!(ss >> action)) { +          continue; +        } +        if (action == "q") { +          return; +        } +        if (action == "u") { +          std::cerr << "Checking for updates..." << std::endl; +          while (true) { +            auto response = client_->receive(0); +            if (response.object) { +              process_response(std::move(response)); +            } else { +              break; +            } +          } +        } else if (action == "l") { +          std::cerr << "Logging out..." << std::endl; +          send_query(td_api::make_object<td_api::logOut>(), {}); +        } else if (action == "m") { +          std::int64_t chat_id; +          ss >> chat_id; +          ss.get(); +          std::string text; +          std::getline(ss, text); + +          std::cerr << "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>(); +          message_content->text_ = td_api::make_object<td_api::formattedText>(); +          message_content->text_->text_ = std::move(text); +          send_message->input_message_content_ = std::move(message_content); + +          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; +                       } +                     }); +        } +      } +    } +  } + + private: +  using Object = td_api::object_ptr<td_api::Object>; +  std::unique_ptr<td::Client> client_; + +  td_api::object_ptr<td_api::AuthorizationState> authorization_state_; +  bool are_authorized_{false}; +  bool need_restart_{false}; +  std::uint64_t current_query_id_{0}; +  std::uint64_t authentication_query_id_{0}; + +  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, std::string> chat_title_; + +  void restart() { +    client_.reset(); +    *this = TdExample(); +  } + +  void send_query(td_api::object_ptr<td_api::Function> f, std::function<void(Object)> handler) { +    auto query_id = next_query_id(); +    if (handler) { +      handlers_.emplace(query_id, std::move(handler)); +    } +    client_->send({query_id, std::move(f)}); +  } + +  void process_response(td::Client::Response response) { +    if (!response.object) { +      return; +    } +    //std::cerr << response.id << " " << to_string(response.object) << std::endl; +    if (response.id == 0) { +      return process_update(std::move(response.object)); +    } +    auto it = handlers_.find(response.id); +    if (it != handlers_.end()) { +      it->second(std::move(response.object)); +    } +  } + +  std::string get_user_name(std::int32_t user_id) { +    auto it = users_.find(user_id); +    if (it == users_.end()) { +      return "unknown user"; +    } +    return it->second->first_name_ + " " + it->second->last_name_; +  } + +  void process_update(td_api::object_ptr<td_api::Object> update) { +    td_api::downcast_call( +        *update, overloaded( +                     [this](td_api::updateAuthorizationState &update_authorization_state) { +                       authorization_state_ = std::move(update_authorization_state.authorization_state_); +                       on_authorization_state_update(); +                     }, +                     [this](td_api::updateNewChat &update_new_chat) { +                       chat_title_[update_new_chat.chat_->id_] = update_new_chat.chat_->title_; +                     }, +                     [this](td_api::updateChatTitle &update_chat_title) { +                       chat_title_[update_chat_title.chat_id_] = update_chat_title.title_; +                     }, +                     [this](td_api::updateUser &update_user) { +                       auto user_id = update_user.user_->id_; +                       users_[user_id] = std::move(update_user.user_); +                     }, +                     [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 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; +                     }, +                     [](auto &update) {})); +  } + +  auto create_authentication_query_handler() { +    return [this, id = authentication_query_id_](Object object) { +      if (id == authentication_query_id_) { +        check_authentication_error(std::move(object)); +      } +    }; +  } + +  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()); +            })); +  } + +  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); +      on_authorization_state_update(); +    } +  } + +  std::uint64_t next_query_id() { +    return ++current_query_id_; +  } +}; + +int main() { +  TdExample example; +  example.loop(); +} diff --git a/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp b/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp new file mode 100644 index 0000000000..6787b37f86 --- /dev/null +++ b/protocols/Telegram/tdlib/td/example/cpp/tdjson_example.cpp @@ -0,0 +1,33 @@ +// +// 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 <iostream> +#include <td/telegram/td_json_client.h> + +// Basic example of TDLib JSON interface usage. +// Native interface should be preferred instead in C++, so here is only an example of +// 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 + +  const double WAIT_TIMEOUT = 10.0;  // seconds +  while (true) { +    const char *result = td_json_client_receive(client, 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 + +      // if (result is UpdateAuthorizationState with authorizationStateClosed) { +      //   break; +      // } + +      std::cout << result << std::endl; +    } +  } + +  td_json_client_destroy(client); +}  | 
