2018-02-26 19:08:47 +01:00
|
|
|
//
|
2022-01-01 01:35:39 +01:00
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
|
2018-02-26 19:08:47 +01:00
|
|
|
//
|
|
|
|
// 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)
|
|
|
|
//
|
2020-06-06 21:51:45 +02:00
|
|
|
#pragma managed(push, off)
|
2018-02-26 19:08:47 +01:00
|
|
|
#include "td/telegram/Client.h"
|
2020-06-06 21:51:45 +02:00
|
|
|
#pragma managed(pop)
|
2018-02-26 19:08:47 +01:00
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
#include "td/telegram/TdDotNetApi.h"
|
|
|
|
|
2018-02-26 19:08:47 +01:00
|
|
|
#include "td/utils/port/CxCli.h"
|
|
|
|
|
2020-06-06 21:51:45 +02:00
|
|
|
#pragma managed(push, off)
|
2018-02-28 11:25:07 +01:00
|
|
|
#include <cstdint>
|
2020-06-06 21:51:45 +02:00
|
|
|
#pragma managed(pop)
|
2018-02-28 11:25:07 +01:00
|
|
|
|
2018-02-28 02:11:29 +01:00
|
|
|
namespace Telegram {
|
|
|
|
namespace Td {
|
2018-02-28 00:09:23 +01:00
|
|
|
|
2018-02-26 19:08:47 +01:00
|
|
|
using namespace CxCli;
|
|
|
|
|
2021-05-20 09:29:50 +02:00
|
|
|
#if !TD_CLI
|
2021-05-20 01:36:47 +02:00
|
|
|
/// <summary>
|
2021-05-20 01:54:49 +02:00
|
|
|
/// A type of callback function that will be called when a message is added to the internal TDLib log.
|
2021-05-20 01:36:47 +02:00
|
|
|
/// </summary>
|
2022-07-08 10:21:31 +02:00
|
|
|
/// <param name="verbosityLevel">Log verbosity level with which the message was added from -1 up to 1024.
|
2021-05-20 17:30:46 +02:00
|
|
|
/// If 0, then TDLib will crash as soon as the callback returns.
|
|
|
|
/// None of the TDLib methods can be called from the callback.</param>
|
2021-05-20 01:54:49 +02:00
|
|
|
/// <param name="message">Null-terminated string with the message added to the log.</param>
|
|
|
|
public delegate void LogMessageCallback(int verbosityLevel, String^ message);
|
2021-05-20 09:29:50 +02:00
|
|
|
#endif
|
2021-05-20 01:36:47 +02:00
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Interface for handler for results of queries to TDLib and incoming updates from TDLib.
|
|
|
|
/// </summary>
|
2018-02-26 19:08:47 +01:00
|
|
|
public interface class ClientResultHandler {
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Callback called on result of query to TDLib or incoming update from TDLib.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="object">Result of query or update of type Telegram.Td.Api.Update about new events.</param>
|
2018-02-28 19:38:21 +01:00
|
|
|
void OnResult(Api::BaseObject^ object);
|
2018-02-26 19:08:47 +01:00
|
|
|
};
|
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Main class for interaction with the TDLib.
|
|
|
|
/// </summary>
|
2018-02-26 19:08:47 +01:00
|
|
|
public ref class Client sealed {
|
|
|
|
public:
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Sends a request to the TDLib.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="function">Object representing a query to the TDLib.</param>
|
|
|
|
/// <param name="handler">Result handler with OnResult method which will be called with result
|
|
|
|
/// of the query or with Telegram.Td.Api.Error as parameter. If it is null, nothing will be called.</param>
|
|
|
|
/// <exception cref="NullReferenceException">Thrown when query is null.</exception>
|
2018-02-28 19:38:21 +01:00
|
|
|
void Send(Api::Function^ function, ClientResultHandler^ handler) {
|
2021-09-27 20:43:14 +02:00
|
|
|
std::uint64_t requestId = Increment(currentRequestId);
|
2018-02-26 19:08:47 +01:00
|
|
|
if (handler != nullptr) {
|
2021-09-27 20:43:14 +02:00
|
|
|
handlers[requestId] = handler;
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
2021-09-27 20:43:14 +02:00
|
|
|
auto request = td::td_api::move_object_as<td::td_api::Function>(ToUnmanaged(function)->get_object_ptr());
|
|
|
|
td::ClientManager::get_manager_singleton()->send(clientId, requestId, std::move(request));
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Synchronously executes a TDLib request. Only a few marked accordingly requests can be executed synchronously.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="function">Object representing a query to the TDLib.</param>
|
|
|
|
/// <returns>Returns request result.</returns>
|
|
|
|
/// <exception cref="NullReferenceException">Thrown when query is null.</exception>
|
2018-10-24 19:23:47 +02:00
|
|
|
static Api::BaseObject^ Execute(Api::Function^ function) {
|
2021-09-27 20:43:14 +02:00
|
|
|
auto request = td::td_api::move_object_as<td::td_api::Function>(ToUnmanaged(function)->get_object_ptr());
|
|
|
|
return Api::FromUnmanaged(*td::ClientManager::execute(std::move(request)));
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Launches a cycle which will fetch all results of queries to TDLib and incoming updates from TDLib.
|
2022-04-03 21:59:28 +02:00
|
|
|
/// Must be called once on a separate dedicated thread on which all updates and query results from all Clients will be handled.
|
2021-09-27 20:43:14 +02:00
|
|
|
/// Never returns.
|
2018-03-15 17:25:51 +01:00
|
|
|
/// </summary>
|
2021-09-27 20:43:14 +02:00
|
|
|
static void Run() {
|
2018-02-26 19:08:47 +01:00
|
|
|
while (true) {
|
2021-09-27 20:43:14 +02:00
|
|
|
auto response = td::ClientManager::get_manager_singleton()->receive(300.0);
|
2018-02-26 19:08:47 +01:00
|
|
|
if (response.object != nullptr) {
|
2021-09-27 20:43:14 +02:00
|
|
|
bool isClosed = response.object->get_id() == td::td_api::updateAuthorizationState::ID &&
|
2018-02-26 19:08:47 +01:00
|
|
|
static_cast<td::td_api::updateAuthorizationState &>(*response.object).authorization_state_->get_id() ==
|
2021-09-27 20:43:14 +02:00
|
|
|
td::td_api::authorizationStateClosed::ID && response.request_id == 0;
|
|
|
|
|
|
|
|
ClientResultHandler^ handler;
|
|
|
|
if (response.request_id == 0 ? updateHandlers.TryGetValue(response.client_id, handler) :
|
|
|
|
handlers.TryRemove(response.request_id, handler)) {
|
|
|
|
// TODO try/catch
|
|
|
|
handler->OnResult(Api::FromUnmanaged(*response.object));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isClosed) {
|
|
|
|
updateHandlers.TryRemove(response.client_id, handler);
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <summary>
|
|
|
|
/// Creates new Client.
|
|
|
|
/// </summary>
|
2020-10-05 19:13:15 +02:00
|
|
|
/// <param name="updateHandler">Handler for incoming updates.</param>
|
2018-03-15 17:25:51 +01:00
|
|
|
/// <returns>Returns created Client.</returns>
|
2020-10-05 19:13:15 +02:00
|
|
|
static Client^ Create(ClientResultHandler^ updateHandler) {
|
|
|
|
return REF_NEW Client(updateHandler);
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
|
|
|
|
2021-05-20 09:29:50 +02:00
|
|
|
#if !TD_CLI
|
2021-05-20 01:36:47 +02:00
|
|
|
/// <summary>
|
2021-05-20 01:54:49 +02:00
|
|
|
/// Sets the callback that will be called when a message is added to the internal TDLib log.
|
|
|
|
/// None of the TDLib methods can be called from the callback.
|
2021-05-20 01:36:47 +02:00
|
|
|
/// </summary>
|
2021-06-02 14:43:56 +02:00
|
|
|
/// <param name="max_verbosity_level">The maximum verbosity level of messages for which the callback will be called.</param>
|
2021-05-20 01:54:49 +02:00
|
|
|
/// <param name="callback">Callback that will be called when a message is added to the internal TDLib log.
|
|
|
|
/// Pass null to remove the callback.</param>
|
|
|
|
static void SetLogMessageCallback(std::int32_t max_verbosity_level, LogMessageCallback^ callback) {
|
2021-05-20 01:36:47 +02:00
|
|
|
std::lock_guard<std::mutex> lock(logMutex);
|
|
|
|
if (callback == nullptr) {
|
2021-09-27 20:43:14 +02:00
|
|
|
td::ClientManager::set_log_message_callback(max_verbosity_level, nullptr);
|
2021-05-20 01:54:49 +02:00
|
|
|
logMessageCallback = nullptr;
|
2021-05-20 01:36:47 +02:00
|
|
|
} else {
|
2021-05-20 01:54:49 +02:00
|
|
|
logMessageCallback = callback;
|
2021-09-27 20:43:14 +02:00
|
|
|
td::ClientManager::set_log_message_callback(max_verbosity_level, LogMessageCallbackWrapper);
|
2021-05-20 01:36:47 +02:00
|
|
|
}
|
|
|
|
}
|
2021-05-20 09:29:50 +02:00
|
|
|
#endif
|
2021-05-20 01:36:47 +02:00
|
|
|
|
2018-02-26 19:08:47 +01:00
|
|
|
private:
|
2020-10-05 19:13:15 +02:00
|
|
|
Client(ClientResultHandler^ updateHandler) {
|
2021-09-27 20:43:14 +02:00
|
|
|
clientId = td::ClientManager::get_manager_singleton()->create_client_id();
|
|
|
|
if (updateHandler != nullptr) {
|
|
|
|
updateHandlers[clientId] = updateHandler;
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
2021-09-27 20:43:14 +02:00
|
|
|
Send(REF_NEW Api::GetOption("version"), nullptr);
|
2018-02-26 19:08:47 +01:00
|
|
|
}
|
2021-05-20 01:36:47 +02:00
|
|
|
|
2021-09-27 20:43:14 +02:00
|
|
|
#if !TD_CLI
|
|
|
|
static std::int64_t currentRequestId;
|
|
|
|
#else
|
|
|
|
static std::int64_t currentRequestId = 0;
|
|
|
|
#endif
|
|
|
|
static ConcurrentDictionary<std::uint64_t, ClientResultHandler^> handlers;
|
|
|
|
static ConcurrentDictionary<std::int32_t, ClientResultHandler^> updateHandlers;
|
|
|
|
std::int32_t clientId;
|
|
|
|
|
2021-05-20 09:29:50 +02:00
|
|
|
#if !TD_CLI
|
2021-05-20 01:36:47 +02:00
|
|
|
static std::mutex logMutex;
|
2021-05-20 01:54:49 +02:00
|
|
|
static LogMessageCallback^ logMessageCallback;
|
2021-05-20 01:36:47 +02:00
|
|
|
|
2021-05-20 01:54:49 +02:00
|
|
|
static void LogMessageCallbackWrapper(int verbosity_level, const char *message) {
|
|
|
|
auto callback = logMessageCallback;
|
|
|
|
if (callback != nullptr) {
|
|
|
|
callback(verbosity_level, string_from_unmanaged(message));
|
|
|
|
}
|
2021-05-20 01:36:47 +02:00
|
|
|
}
|
2021-05-20 09:29:50 +02:00
|
|
|
#endif
|
2018-02-26 19:08:47 +01:00
|
|
|
};
|
|
|
|
|
2021-05-20 09:29:50 +02:00
|
|
|
#if !TD_CLI
|
2021-09-27 20:43:14 +02:00
|
|
|
std::int64_t Client::currentRequestId = 0;
|
|
|
|
ConcurrentDictionary<std::uint64_t, ClientResultHandler^> Client::handlers;
|
|
|
|
ConcurrentDictionary<std::int32_t, ClientResultHandler^> Client::updateHandlers;
|
|
|
|
|
2021-05-20 01:36:47 +02:00
|
|
|
std::mutex Client::logMutex;
|
2021-05-20 01:54:49 +02:00
|
|
|
LogMessageCallback^ Client::logMessageCallback;
|
2021-05-20 09:29:50 +02:00
|
|
|
#endif
|
2021-05-20 01:36:47 +02:00
|
|
|
|
2018-02-28 02:11:29 +01:00
|
|
|
} // namespace Td
|
|
|
|
} // namespace Telegram
|