Telegram API и библиотека TDLib для .NET платформ

image
Доброго времени суток! В Telegram существует два вида API: Telegram Bot API (обыкновенный бот с пометкой «бот») и Telegram API (клиент и юзербот, который обладает больше функционалом, чем просто бот). В этой статье пойдет речь о втором виде, а именно: что требуется для взаимодействия с Telegram API, какие средства нужны для написания кода своего юзербота на языке C#, как их правильно установить, а также каким образом использовать их.

Администраторам групп и чатов порой необходимо пользоваться таким полезным инструментом как боты, а кому-то и вовсе требуется свой клиент для запросов серверу Telegram. Для взаимодействия с ботами существует немалое количество готовых библиотек для различных языков и платформ, но если требуется написать собственную программу или библиотеку (возможно, написанные другими людьми библиотеки ограничены и не содержат требуемых вам функций), то для этого Telegram имеет собственный API.

Telegram поддерживает два варианта API: Telegram Bot API (обычный бот) и Telegram API (собственный клиент или юзербот). В сегодняшнем материале речь пойдет о втором случае, когда нужно свой аккаунт использовать как бота или же для каких-либо иных действий. Например, с помощью Telegram API можно написать полностью свой клиент, который будет работать точно также как и основной «телеграммовский» клиент, можно реализовать отображение реального времени на вашей аватарке, можно использовать своего юзербота как сканер для защиты вашего чата от спама, флуда, «рейдов» и т. д. В общем, применений найдется много.

Для реализации юзербота потребуются две вещи: библиотека TDLib и любой язык, который способен выполнять функции языка C (в нашем случае используем C#).

Чтобы обеспечить взаимодействие между вашим клиентом и сервером Telegram, используется кроссплатформенная библиотека TDLib (Telegram Database Library). Будем устанавливать ее для Visual Studio (нужна версия от 2015 и выше, а также CMake в консоли).


TDLib через NuGet

Обратите внимание, что библиотека TDLib, устанавливаемая через NuGet, и библиотека Telegram.Td.dll, собираемая через CMake — это разные вещи, обладающие несколько разными интерфейсами. В нашем случае мы используем собираемый через CMake вариант.

TDLib имеет следующие зависимости, т. е. на вашем компьютере это должно быть:


  • компилятор C++14 (Visual Studio имеет свой компилятор MSVC);
  • Библиотека OpenSSL;
  • Библиотека zlib;
  • gperf (только сборка);
  • CMake (3.0.2+, только сборка).

Для установки необходимых зависимостей, выполните следующие команды в командной строке (обратите внимание, что требуется git):

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
git checkout 1b1ae50e1a69f7c659bd7d731e80b358d21c86ad
.\bootstrap-vcpkg.bat
.\vcpkg.exe install gperf:x64-windows gperf:x86-windows openssl:x64-windows openssl:x86-windows zlib:x64-windows zlib:x86-windows

Далее скачиваем саму библиотеку и собираем её для .NET-проектов:


  1. Переходим в папку (в командной строке) /example/csharp, т.е. туда, где будем собирать нашу библиотеку


  2. Создаём папку, куда будем собирать библиотеку, и переходим в неё:

    mkdir build
    cd build

  3. Настраиваем сборку библиотеки в зависимости от разрядности системы (x32 или x64); где »…path to vcpkg…», указываем путь до скачанного ранее vcpkg:


    • Для x32:
      cmake -A Win32 -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake ../../..
    • Для x64:
      cmake -A x64 -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake ../../..

  4. Собираем библиотеку в зависимости от требуемой конфигурации (Release или Debug):


Готово! Теперь в папке build/Release или build/Debug (в зависимости от того, что вы выбрали) находится готовый файл Telegram.Td.dll, который и нужно использовать в своем проекте.

Давайте теперь подключим её в Visual Studio:


  1. Добавляем ссылку на наш файл Telegram.Td.dll, это можно сделать по следующему пути:
    Проект → Добавить → Ссылка на проект → Обзор → Обзор
    Ставим галочку напротив нашей библиотеки.
    image


  2. Запускаем проект, для того, чтобы создать папку с exe- и dll-файлами нашей программы, и туда докидываем следующие dll, которые можно взять из той же папки, где мы получили собранную библиотеку Telegram.Td.dll: libcrypto-1_1-x64.dll, libssl-1_1-x64.dll, zlib1.dll.
    Должен получиться похожий набор файлов, но главное, чтобы все 4 dll-файла для нашей библиотеки были вместе, включая саму библиотеку:
    image


Теперь мы можем подключать библиотеку в коде:

using Td = Telegram.Td;
using TdApi = Telegram.Td.Api;

Перед тем, как полноценно использовать библиотеку, нужно получить id и hash — своеобразная защита, чтобы пользоваться юзерботом можно было только с вашего разрешения. Их можно получить здесь:


  1. Войдите, пройдите небольшую аутентификацию и создайте новое приложение (поля URL и Description можно оставить пустыми, в Platform выберите Desktop):
    image


  2. В разделе App Configuration найдите два поля: App api_id и App api_hash. Скопируйте их, они понадобятся для дальнейшей работы с TDLib.
    image


Рассмотрим готовый вариант использования, находящийся в самой папке библиотеки, которую мы скачали до этого: …\TDLib\td-master\example\csharp\TdExample.cs

Перед тем, как запускать для проверки этот пример в коде, в методе OnAuthorizationStateUpdated, содержащем все необходимое для авторизации, включая обработки текущих стадий авторизации, стоит исправить эти две строки на ваш api_id и api_hash, которые мы получили до этого:

request.ApiId = /*api_id*/;
request.ApiHash = /*api_hash*/;

Разберемся с основным методом Main, где до основного цикла происходит процедура создания клиента:

Td.Client.Execute(new TdApi.SetLogVerbosityLevel(0));
if (Td.Client.Execute(new TdApi.SetLogStream(new TdApi.LogStreamFile("tdlib.log", 1 << 27, false))) is TdApi.Error) {
    throw new System.IO.IOException("Write access to the current directory is required");
}
new Thread(() => {
    Thread.CurrentThread.IsBackground = true;
    Td.Client.Run();
}).Start();
_client = CreateTdClient();
_defaultHandler.OnResult(Td.Client.Execute(new TdApi.GetTextEntities("@telegram /test_command https://telegram.org telegram.me @gif @test")));

В целом, эту часть трогать не стоит, она необходима, чтобы Ваш клиент работал правильно и вообще работал.

Далее идёт основной цикл:

while (!_needQuit) {
    // Ожидание авторизации
    _gotAuthorization.Reset();
    _gotAuthorization.WaitOne();
    // Предзагрузка чатов
    _client.Send(new TdApi.LoadChats(null, 100), _defaultHandler);
    // Пока пользователь авторизован, происходит обработка команд в консоли.
    // Если же окажется, что пользователь разлогинился (метод GetCommand содержит данную
    // возможность), то авторизация происходит снова.
    // Выход из цикла организуется, когда пользователь выходит из клиента
    // (опять же метод GetCommand содержит данную возможность).
    while (_haveAuthorization)
    {
        GetCommand();
    }
}

Пример содержит также два достаточно важных класса: DefaultHandler и UpdateHandler. В них происходит обработка всех пришедших данных от сервера Telegram.

UpdateHandler нужен, когда происходит какое-то обновление (новые сообщения, информация, что пользователь в текущем клиенте разлогинился, и т. д.).
Например, можно написать следующее:

void Td.ClientResultHandler.OnResult(TdApi.BaseObject @object)
{
    if (@object is TdApi.UpdateAuthorizationState)
    {
        OnAuthorizationStateUpdated((@object as TdApi.UpdateAuthorizationState).AuthorizationState);
     }
    else if (@object is TdApi.UpdateNewMessage)
    {
        // Здесь - вызов собственного метода, где в качестве аргумента можно указать (@object as TdApi.UpdateNewMessage).Message,
        // чтобы обрабатывать сообщения, которые пришли.
        // Таким образом, можно реализовать бота, отвечающего на различные команды в чате.
    }
}

DefaultHandler нужен, когда мы где-то в коде посылаем команду-запрос с помощью метода Send:

_client.Send(new /*метод*/, _defaultHandler);

При этом ответ на этот запрос обрабатывается в DefaultHandler:

private class DefaultHandler : Td.ClientResultHandler
{
    void Td.ClientResultHandler.OnResult(TdApi.BaseObject @object)
    {
        // Здесь происходит обработка @object, который и является ответом на наш запрос.
        // @object может быть любым классом, который в документации указан в качестве 
        // возвращаемого к методу, сделавшему запрос
    }
}

Все доступные методы и описание можно найти здесь, все классы — здесь.
Вашу собственную программу удобно строить поверх этого примера или все взаимодействие клиент-сервер можно спокойно реализовать в качестве отдельного класса.

TDLib является удобным инструментом для реализации собственного клиента на .NET-платформе, но, к сожалению, для других систем, кроме тех, что на базе Windows, этот вариант создания своего клиента не подходит, поэтому можно воспользоваться JSON-интерфейсом через P/Invoke, если нужен именно C#.

mxuanbovcusqgmqdgugvpnql8vq.jpeg

© Habrahabr.ru