1 место Разбираем User - API Telegram по косточкам

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
Телеграм предоставляет для разработчиков два API: для работы с ботами (давайте будем называть его Bot-API) и для работы с пользователями (назовем его User-API). Т.к. данная статья посвящена User-API, далее по тексту я его буду упоминать как просто API, а что относится к Bot-API - так и буду упоминать.
При работе с Телеграм, бывают ситуации, когда через Bot-API не возможно реализовать нужные действия, и необходимо их выполнить от имени аккаунта пользователя, а не бота. Поэтому, попытаемся разобраться, как все же работать с Телеграм через его API.


Знаю, многие даже просто окунаясь в API Телеграм, хватаются за голову из-за не стандартной реализации. Но на деле, если вникнуть и разобраться, то все довольно просто.
Вся сложность, заключается в том, что API работает через свой протокол –
MTProto, и работать через простые POST/GET запросы здесь не получится. На помощь приходят библиотеки, которые работают с данным API через нужный протокол. В настоящее время есть немало библиотек, которые позволяют это делать под C#, но практически все они работают на более новых версиях C#, и не всегда получается использовать их совместно с Zennoposter. Лично я использую библиотеку TLSharp, как одну из первых вышедшую для работы с API Телеграм под C#.
До недавнего времени, библиотека поддерживалась уже сложившимся комьюнити, но не так давно репозиторий был переведен в статус архивного. Почему пал выбор на эту библиотеку? Потому что на ней все еще можно работать через Zennoposter.
Т.к. Телеграм в канун нового года внес существенные ограничения для работы с API – минимальная версия API для работы – требуется 133 версия - в основном это было связано с переходом ID с типа int на long.

Давайте еще разберемся с
Layer, что это такое? При общении в кругах пользователей API, часто упоминаются: лайер, layer, слой, уровень, кто как называет и все это по простому - номер версии API. С каждой новой версией – добавляется новый функционал, и не всегда более новая версия совместима с более старой.

На какой же версии, работает TLSharp? В текущей реализации, там всё ещё - 66 версия, в то время как на текущий момент последняя публичная версия - 139. Как же нам быть? Специально для нашего комьюнити, я выкладываю доработанную мной библиотеку, с рабочей версией - 133, на которую ориентируется Телеграм, как на
минимально рабочую.
Реализация доработанной библиотеки – является форком от последней версии TLSharp, с моими доработками, поэтому работает как есть. Если у вас есть претензии - можете отказаться от ее использования.
Так же доработанная версия - позволяет указывать различные параметры устройств для подключения, чем самым достигается возможность управлять рандомизацией необходимых устройств.
Есть конечно и минусы в данной библиотеке, которые можно обойти: при переходе на 133 версию, Телеграм изменил в корне проверку пароля 2ФА, и в доработанной версии проверка пароля не реализована, поэтому авторизация аккаунтов возможна только без установленного облачного пароля, и есть еще минус уже самой библиотеки: при скачивании некоторых медиа файлов, расположенных в датацентре отличном от аккаунта - сохраненный профиль будет биться, и будет нужна повторная авторизация. Но тут больше не баг, а из-за заложенной архитектуры библиотеки, нет возможности подключаться к временному датацентру, где хранится определенный медиа файл, для его скачивания.

Настройка Layer
В нашей версии библиотеки версия API статична и адаптирована под версию 133. Поэтому мы будем ориентироваться на нее, и для этого нам необходимо зайти в документацию, выбрать любой метод, и установить нужный на Layer на 133.
Например зайдем в метод
auth.sendCode и изменим Layer 139 на 133, и далее при сёрфинге по всей документации версия будет отображаться выбранная нами:
chrome_2022-05-21_21-03-48.jpg chrome_2022-05-21_21-07-41.jpg

Стилизация
Важная особенность: все сущности в нашей библиотеке написаны в стиле – PascalCase, т.е. все слова начинаются с большой буквы без подчеркиваний и не зависит от запрос это или параметр.
В документации же Телеграм – методы описаны в стиле camelCase (первая буква первого слова в нижнем регистре, последующие первые буквы слов в верхнем), а параметры в стиле snake_case (слова разделены нижним подчеркиванием и все с малой буквы).
Нужно просто привыкнуть и все переводить в PascalCase, и добавлять в начало TL для сущностей и TLRequest для запросов.


API данные
Перейдем к делу! Для работы с любым API, требуется по крайней мере api ключ, который выдается поставщиком API. В Телеграм, для работы с API используется одновременно – два ключа: Api_ID и Api_Hash, получить которые можно на странице создания своего приложения.
Ключи всегда используются в паре, поэтому в обиходе их обычно называют – пара.


Документация API
Данные для работы, мы получили, давайте разберемся, с документацией.
Все доступные методы, для работы с API, Телеграм хорошо
задокументированы.
Все их описывать – не реально большой объем информации, поэтому нам главное уловить суть, научиться пользоваться документацией, и используя описание - пользоваться нашей библиотекой.
Поэтому предлагаю детально разобрать: авторизацию аккаунта в своем приложении, что даст нам сохраненный профиль, для дальнейшей работы с ним.


Настройки проекта Zennoposter
Для работы нам понадобятся библиотеки, добавим в ссылки GAC нашего проекта Zennoposter, библиотеки:
StarkSoftProxy.dll, TeleSharp.TL.dll и TLSharp.Core.dll

ProjectMaker_2022-05-21_21-45-57.jpg

Добавим директивы using

ProjectMaker_2022-05-21_21-46-32.jpg


Авторизация
Что такое авторизация? Это создание новой сессии в нашем приложении, и сохранение ее в файл в виде профиля. Простыми словами - вы скачиваете официальный клиент, авторизуетесь в нем, введя номер телефона и в ответ вводите код, полученный в каком-либо уже авторизованном приложении, и дальше уже пользуетесь приложением. То же самое нам нужно сделать, но уже для своего приложения, данные которого мы создали выше.
Нужно учесть, что авторизация это не регистрация. Авторизовать можно только уже зарегистрированный номер в Телеграм.
Для авторизации, нам нужно отправить в Телеграм всего 2 запроса:
auth.sendCode и auth.signIn. Первый позволяет отправить код. Второй отправляет уже полученный код из приложения, и собственно в результате мы получаем авторизацию в нашем приложении.
chrome_2022-05-21_20-59-05.jpg

Создаем первый запрос
Давайте разберемся, как же адаптировать запросы указанные в документации (auth.sendCode), к запросам для нашей библиотеки (TeleSharp.TL.Auth.TLRequestSendCode): auth.sendCode => TeleSharp.TL.Auth.TLRequestSendCode
notepad++_2022-05-21_22-53-11.jpg

Разберем:
  • TeleSharp.TL – пространство имен, где расположены все наши сущности. Все классы ищем именно тут.
  • Auth - пространство имен, где расположены сущности для авторизации
    ProjectMaker_2022-05-21_22-57-39.jpg
  • TLRequest – приставка, которая добавляется ко всем сущностям, которые осуществляют запрос, то есть ко всем эти элементам из документации
    ProjectMaker_2022-05-21_22-58-51.jpg
В итоге у нас получилось: TeleSharp.TL.Auth.TLRequestSendCode, опираясь на документацию
chrome_2022-05-21_23-05-11.jpg 2022-05-21_23-20-31.jpg

Это путь к нашему классу для запроса. Создадим сам объект запроса:
C#:
var sentRequest = new TeleSharp.TL.Auth.TLRequestSendCode ();
Так, мы создали объект, но для запроса, нам нужно передать параметры в этот запрос (по аналогии, можем сравнить с параметрами GET запроса, передаваемыми после ? в адресной строке: ?name1=value1&name2=value2…)

Смотрим в документации, какие параметры нам нужно передать для запроса
sendCode:
chrome_2022-05-21_23-31-18.jpg

Разберем:
  • phone_number – передаем в параметр номер телефона для авторизации
  • api_id – API ключ нашего приложения
  • api_hash – API ключ нашего приложения
  • settings – настройка типа отправленного кода, для более детального изучения типа – перейдем по ссылке CodeSettings
    chrome_2022-05-21_23-55-50.jpg
Т.к. параметр CodeSettings у нас не простого типа (int, string, bool …), а данный параметр это новый объект, который может иметь уже свои параметры. Что бы посмотреть, что мы сюда должны передать – переходим в документацию конструктора нашего параметра codeSettings:
chrome_2022-05-22_00-02-29.jpg

И смотрим, у данного объекта есть уже свои параметры, и вот тут уже появляется во всех параметрах знак ? – что показывает нам, что данные параметры не обязательные и их можно не передавать:
2022-05-22_00-07-15.jpg

Что нам дают не обязательные параметры?
Мы можем уточнить за счет них, настройки типа отправленного кода.
Про типы расписано в
документации.

Разберем:

  • allow_flashcall - Разрешить ли подтверждение телефона с помощью флэш-звонка, где кодом будет являться номер телефона входящего звонка.
  • current_number - Если номер телефона используется на текущем устройстве.
  • allow_app_hash - Если требуется токен, который будет включен в отправленные SMS-сообщения: требуется в более новых версиях Android, чтобы использовать API-интерфейс Android приемника SMS.
  • allow_missed_call - Поддерживает ли это устройство получение кода с помощью метода auth.codeTypeMissedCall.
  • logout_tokens - Ранее сохраненные токены выхода
Все параметры у нас не обязательные, поэтому можно передать "пустой" объект CodeSettings.
Как нам его создать в нашей библиотеке?
Т.к. этот объект уже не является запросом (к которому мы добавляли TLRequest), а простой параметр, то мы добавляем просто TL в начало имени, ну и согласно нашему стилю, ищем в нашей библиотеке CodeSettings => TLCodeSettings:

ProjectMaker_2022-05-22_00-28-10.jpg

В итоге, нам в параметр запроса Settings – нам нужно передать объект
C#:
new TeleSharp.TL.TLCodeSettings ()
Давайте теперь все разобранные параметры, добавим к нашему запросу:
ProjectMaker_2022-05-22_00-38-37.jpg

C#:
var sentRequest = new TeleSharp.TL.Auth.TLRequestSendCode();
sentRequest.PhoneNumber = "12345678";
Точно так же заполняем остальные параметры (API пару и настройки):
ProjectMaker_2022-05-22_00-50-51.jpg

Сделаем небольшой рефакторинг, т.е. присвоим все параметры не после создания объекта, а в момент создания:
ProjectMaker_2022-05-22_00-53-57.jpg

В итоге то же самое, но код стал чище и читабельнее. Далее я буду сразу так создавать объекты, если вам тяжело разобрать, можете формировать объект с "поэтапным" присвоением параметров, как расписал выше.
C#:
var sentRequest = new TeleSharp.TL.Auth.TLRequestSendCode ()
{
    PhoneNumber = "12345678",
    ApiId = 16623,
    ApiHash = "8c9dbfe58437d1739540f5d53c72ae4b",
    Settings = new TeleSharp.TL.TLCodeSettings ()
};

Создаем клиент для запросов
Всё, с созданием объекта для запроса мы разобрались. Теперь нам надо этот объект отправить на сервер Телеграм. Для отправки запроса, нам нужно создать объект – client, который уже будет обрабатывать наши созданные запросы, и работать с серверами Телеграм по тому самому протоколу MTProto.
Всем этим занимается библиотека, нам главное отправить запрос и получить ответ. А дальше мы уже будем разбирать ответ от Телеграм.

Для создания клиента – нам нужен класс TLSharp.Core.TelegramClient нашей библиотеки.
Смотрим в подсказках, что нам нужно для создания экземпляра объекта данного класса.
В первой перегрузке нужны параметры:

ProjectMaker_2022-05-22_01-08-02.jpg
  • int apiId – наш API ключ приложения
  • string apiHash - наш API ключ приложения
  • ISessionStore store – интерфейс, который вы можете реализовать для работы с сохраняемым профилем. В данной библиотеке зашит формат хранимых сессий в бинарной сериализацией данных. Расширение данных профилей будет - *.dat
  • string sessionUserId – путь к нашему профилю. Я в примерах буду файл профиля именовать номером телефона, а расширение файла уже будет подставляться в самой библиотеке.
  • TcpClientConnectionHandler handler – хендлер нам будет нужен для работы запросов внутри библиотеки через наши прокси. Для использования – будем использовать библиотеку StarkSoftProxy, которая то же немного подправлена мной, для удобства работы.
  • DataCenterIPVersion dcIpVersion – тип IP адреса Telegram, к которому мы будем обращаться (IP v4/v6)

C#:
// Подготовим данные
string phone = "1234567890"; // Номер телефона
string dirProfiles = @"D:\Profiles\"; // Путь к папке, где будут храниться профили
string pathProfile = Path.Combine(dirProfiles, phone); // Путь к файлу профиля

var proxy = new ProxyStark("socks5://user:password@IP:port"); // Создаем объект прокси

// Создаем объект клиента:
var client = new TLSharp.Core.TelegramClient(16623, "8c9dbfe58437d1739540f5d53c72ae4b", null, pathProfile, proxy.SetProxy);

// Если прокси не используем, просто не передаем последний параметр:
var client = new TLSharp.Core.TelegramClient(16623, "8c9dbfe58437d1739540f5d53c72ae4b", null, pathProfile);
Это стандартные параметры для создания клиента, заложенные в библиотеке. Но нам надо использовать различные параметры, для инициализации подключения к серверу, которые используются внутри самой библиотеки. Для передачи всех этих параметров, я создал внутри библиотеки класс TLSharp.Core.AppData, и при помощи второй перегрузки создания клиента, мы сможем уже снаружи изменять все параметры подключения.
Для этого воспользуемся второй перегрузкой конструктора класса:

ProjectMaker_2022-05-22_01-41-03.jpg

Здесь вместо двух первых параметров – передаем объект класса AppData с нужными нам параметрами уже для подключения:
ProjectMaker_2022-05-23_01-34-16.jpg

C#:
var app = new TLSharp.Core.AppData(16623, "8c9dbfe58437d1739540f5d53c72ae4b")
{
    DeviceModel = "Desktop",    // Модель нашего устройства
    AppVersion = "1.4.8 x64",    // Версия нашего приложения
    LangCode = "ru",            // Язык нашего приложения
    SystemLangCode = "ru",      // Язык нашей системы
    SystemVersion = "Windows 10", // Версия нашей системы
};
Все эти параметры должны рандомизироваться, но в рамках реальных устройств. И тут своего рода то же целая наука, есть даже курсы, по правильному подбору данных параметров, ведь от них зависит выживаемость и работоспособность аккаунтов, которые будут работать через наши запросы.

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

ProjectMaker_2022-05-23_00-48-14.jpg
C#:
var client = new TLSharp.Core.TelegramClient(app, sessionUserId: pathProfile, handler: proxy.SetProxy);
Отправляем первые запрос
Клиент у нас создан.
Пора отправить наш первый запрос к Телеграм и установить соединение с сервером. Делаем это вызвав метод Connect() у нашего клиента:

C#:
client.Connect();
Если вызов данного метода не выдал исключения, то у нас все нормально, и мы успешно подключились к серверу Телеграм. Но если будут какие ошибки, нам лучше их "поймать", для этого, лучше всего обернуть все наши действия в конструкцию try{} catch{}
ProjectMaker_2022-05-23_00-50-55.jpg

Идем дальше. Соединение установлено, теперь можно отправить подготовленный нами выше запрос в Телеграм. Для отправки всех запросов, будем использовать метод SendRequest нашей библиотеки.

Давайте разберем, что нам нужно передать:

C#:
var responseSent = client.SendRequest<T>(sentRequest);
  • sentRequest – подготовленный нами запрос
  • T – здесь надо указать класс, экземпляр которого нам должен вернуться в ответе. Где его найти? Тип ответа, который вернет Телеграм – указан в документации метода запроса, в разделе Result:
    chrome_2022-05-22_02-10-20.jpg
Видим, что результатом ответа будет - auth.SentCode. Следуя нашим правилам библиотеки, ищем класс, который вернется в ответе auth.SentCode => TeleSharp.TL.Auth.TLSentCode:
ProjectMaker_2022-05-22_02-14-24.jpg

Этот класс и вставляем вместо T – в нашем запросе, получаем наш готовый метод для запроса:
C#:
var responseSent = client.SendRequest<TeleSharp.TL.Auth.TLSentCode>(sentRequest);
Данный код выполнит уже наш запрос, и если нет ошибок, присвоит переменной responseSent значение ответа, в виде объекта класса TeleSharp.TL.Auth.TLSentCode.
Отправив данный запрос, мы запросили у Телеграм код, для авторизации на новом устройстве.


Разбираем полученный ответ отправленного запроса
Что бы посмотреть, какая информация нам вернется в ответе, смотрим в документации.
chrome_2022-05-22_02-17-01.jpg 2022-05-22_02-19-14.jpg

Эти параметры, мы сможем получить из ответа
ProjectMaker_2022-05-22_02-27-25.jpg

Какие данные нам нужны из ответа? Самый необходимы параметр, это phone_code_hash – хэш, который нам будет нужен в следующем запросе. Записываем его в нашу переменную:
C#:
var hash = responseSent.PhoneCodeHash;
Что еще тут есть интересного?
type – тип отправленного кода, точнее даже, нам Телеграм сообщает, куда он оправил код. Какие есть варианты? Можем посмотреть опять в
документации:
2022-05-22_02-36-43.jpg

В данном параметре type – будет объект класса, посмотрим какого:
ProjectMaker_2022-05-22_02-38-56.jpg

Видим, что в Type – Абстрактный класс (есть приставка Abs), соответственно, в данном свойстве может лежать любой экземпляр одного из классов:
2022-05-22_02-46-28.jpg

Давайте попробуем определить, куда же Телеграм отправил наш код:
ProjectMaker_2022-05-22_02-49-21.jpg
В коде это выглядит:
C#:
var responseSent = client.SendRequest<TeleSharp.TL.Auth.TLSentCode>(sentRequest);
var type = responseSent.Type;
if(type is TeleSharp.TL.Auth.TLSentCodeTypeApp)
{
    // Код был отправлен в приложение
}
else if(type is TeleSharp.TL.Auth.TLSentCodeTypeSms)
{
    // Код был отправлен СМС на телефон
}
else if(type is TeleSharp.TL.Auth.TLSentCodeTypeCall)
{
    // Код был отправлен звонком на телефон
}
else if(type is TeleSharp.TL.Auth.TLSentCodeTypeFlashCall)
{
    // Код был отправлен флеш-звонком
}
Тут уже вам решать, как воспользоваться полученной информацией.
Точно также мы сможем из ответа - определить, куда Телеграм отправит следующий код, из свойства next_type (responseSent.NextType нашего результата). Здесь результат лежит так же в абстрактном классе

ProjectMaker_2022-05-22_03-02-49.jpg

Описания классов, можем смотреть auth.CodeType
Можете сами потренироваться и определить, куда же Телеграм отправит следующий код.

Получаем код из приложения
В рамках данной статьи, я не буду углубляться, каким способом передать полученный нами код, то ли вы через всплывающую форму сделаете запрос кода, то ли через текстовый файл, то ли еще каким либо образом. В текущем проекте мы просто разделим код авторизации на два кубика, и будем выполнять код пошагово и впишем полученный код непосредственно в переменную Zennoposter'a: project.Variables["code"].Value.

Что бы отправить код в Телеграм, на том же подключении при котором мы и запросили код, воспользуемся контекстом (project.Context["client"]), для передачи объекта между кубиками.
А также нужные нам номер телефона и хэш – передадим через переменные Zennoposter'a project.Variables["phone"].Value и project.Variables["hash"].Value


Отправляем второй запрос с кодом
А мы давайте пойдем дальше, и закончим уже начатую с вами авторизацию.
После нашего отправленного первого запроса, Телеграм отправит код, скорее всего в приложение. Смотрим в любом удобном клиенте пятизначный цифровой код, в переписке от Telegram.

Следующим этапом, нам надо отправить запрос с полученным кодом.
Идем в документацию и смотрим, нужный нам
метод:
chrome_2022-05-22_03-09-47.jpg

Согласно обязательным параметрам, нам нужно передать: номер телефона, хэш, полученный из результата первого запроса responseSent и код полученный из приложения.
chrome_2022-05-22_03-11-04.jpg

Создадим запрос для отправки кода, подставив сразу все нужные переменные:

C#:
var signInRequest = new TeleSharp.TL.Auth.TLRequestSignIn()
{
    PhoneNumber = project.Variables["phone"].Value,
    PhoneCodeHash = project.Variables["hash"].Value,
    PhoneCode = project.Variables["code"].Value
};
Разберемся с ответом. В ответ будем ждать уже объект авторизации
chrome_2022-05-22_03-30-45.jpg

Тут мы видим, что в ответ может прийти или объект auth.authorization или auth.authorizationSignUpRequired
2022-05-22_03-34-16.jpg

Это значит, что в нашей библиотеке ответом будет абстрактный класс, попробуем его найти:
ProjectMaker_2022-05-22_03-38-30.jpg

TeleSharp.TL.Auth.TLAbsAuthorization – этот класс будет ответом, и нам нужно указать его в методе запроса:
C#:
var responseSignIn = client.SendRequest<TeleSharp.TL.Auth.TLAbsAuthorization>(signInRequest);
Данный код отправит в Телеграм запрос, получит ответ в виде объекта класса TeleSharp.TL.Auth.TLAbsAuthorization, и присвоит переменной responseSignIn.

Разбираем полученный ответ второго запроса
Если запрос выполнен успешно, то в переменной responseSignIn будет лежать результат, иначе будет библиотекой выдано исключение, которое нам нужно будет обрабатывать. А сейчас предположим, что у нас получен успешный ответ, давайте его разберем:

Для начала, нам нужно определить тип полученного ответа:

C#:
if(responseSignIn is TeleSharp.TL.Auth.TLAuthorization)
{
    // Успешная авторизация. Если интересно, можем отсюда получить данные текущего пользователя
    var authorization = (TeleSharp.TL.Auth.TLAuthorization)responseSignIn;
    var user = authorization.User as TLUser;
    var lastName = user.LastName;
    var firstName = user.FirstName;
    var phone = user.Phone;
    var username = user.Username;
}
else if(responseSignIn is TeleSharp.TL.Auth.TLAuthorizationSignUpRequired)
{
    // Учетная запись с таким номером телефона не существует в Telegram: пользователь должен зарегистрироваться
}
Успешная авторизация!
Всё, мы прошли авторизацию в нашем приложении, теперь дальше можно работать с нашим аккаунтом, используя всю мощь API Телеграм.



Получаем диалоги аккаунта
В заключении, давайте сделаем запрос, получив все диалоги текущего аккаунта. Используем метод messages.getDialogs
chrome_2022-05-22_04-02-49.jpg

Смотрим обязательные параметры и результат:
chrome_2022-05-22_04-05-14.jpg

Кроме простых типов, у нас есть объект в параметрах запроса, это offset_peer
Смотрим, сюда нужно передать один из объектов, и т.к. мы запрашиваем диалоги текущего пользователя, нас интересует объект inputPeerSelf.
Смотрим его параметры и видим, что параметры у данного класса отсутствуют.

chrome_2022-05-22_23-34-35.jpg

Ищем его теперь в нашей библиотеке:
ProjectMaker_2022-05-22_04-11-50.jpg


В ответе будет messages.Dialogs, значит у нас это будет абстрактный класс
ProjectMaker_2022-05-22_04-14-36.jpg

Составляем запрос:
C#:
var requestDialog = new TeleSharp.TL.Messages.TLRequestGetDialogs()
{
    OffsetDate = 0,
    OffsetId = 0,
    OffsetPeer = new TeleSharp.TL.TLInputPeerSelf(),
    Limit = 100,
    Hash = 0
};
Параметры OffsetDate и OffsetId – используются для пагинации, и запросов нужной "страницы". Подробно все расписано в документации.

Делаем сам запрос:

C#:
var responseDialog = client.SendRequest<TeleSharp.TL.Messages.TLAbsDialogs>(requestDialog);
Обрабатываем ответ:
C#:
if(responseDialog is TeleSharp.TL.Messages.TLDialogs)
{
    // Полный список чатов с сообщениями и вспомогательными данными. Если у аккаунта не более 100 диалогов
}
else if (responseDialog is TeleSharp.TL.Messages.TLDialogsSlice)
{
    // Неполный список диалогов с сообщениями и вспомогательными данными. В одном ответе телеграм отдает не более 100 диалогов. Если их больше - будет данный тип объекта. Отличается от TLDialogs - только наличием свойства Count с информацией о общем количестве диалогов.
}
else if (responseDialog is TeleSharp.TL.Messages.TLDialogsNotModified)
{
    // Диалоги не изменились.
}

Разберем ответ, когда диалогов не более 100, т.е. получен объект класса TeleSharp.TL.Messages.TLDialogs.
C#:
// Полный список чатов с сообщениями и вспомогательными данными. Если у аккаунта не более 100 диалогов
var dialogs = (TeleSharp.TL.Messages.TLDialogs)responseDialog;

// получим список чатов на аккаунте
var chats = dialogs.Chats;
Из документации видим, что в свойстве chats будет коллекция из разных объектов: допустим, нас интересуют только чаты/группы/каналы.

Видим что чаты будут выданы объектами
chat. Делаем выборку из коллекции определенного типа объектов:
C#:
var onlyChats = chats.OfType<TeleSharp.TL.TLChat>();
Для выборки из коллекции объектов каналов:
C#:
var groupsChannels = chats.OfType<TeleSharp.TL.TLChannel>();
Т.к. каналы и супергруппы у нас идут одним объектом, мы их можем разделить за счет выборки, по свойству, указывающему на принадлежность к каналу
C#:
var onlyChannels = chats.OfType<TeleSharp.TL.TLChannel>().Where(x => x.Broadcast);
var onlyGroups = chats.OfType<TeleSharp.TL.TLChannel>().Where(x => x.Megagroup);
Все свойства, которые мы можем использовать расписаны в документации объектов channel

P.S.
Пытался объяснить максимально доступно по разбору User-API Телеграм.
Материал излагал, в обучающем стиле, поэтому все используемые классы указывал с полными путями, не используя юзинги, для сокращенного написания кода, что бы было понятнее расположение классов в библиотеке.
Надеюсь расписанная мной информация, поможет вам для старта в это увлекательное API.

Всем удачного изучения и использования!

.



 
Тема статьи
Соц. сети
Номер конкурса статей
Семнадцатый конкурс статей

Вложения

Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Последнее редактирование модератором:

sergio197675

Client
Регистрация
21.09.2019
Сообщения
360
Благодарностей
318
Баллы
63
То что я давно ждал от авторов , приогромнейшее спасибо!
 
  • Спасибо
Реакции: stud

radv

Client
Регистрация
11.05.2015
Сообщения
3 820
Благодарностей
2 030
Баллы
113
:ay: Спасибо за обзор UserAPI, а то по BotAPI полно в интернете обзоров, а по юзерапи мало.:az:
 
  • Спасибо
Реакции: stud

OlegR

Client
Регистрация
11.06.2015
Сообщения
244
Благодарностей
250
Баллы
63
Приветствую. как здесь можно настроить работу через прокси? в самом апи такая возможность есть?
 
  • Спасибо
Реакции: stud

kane16

Client
Регистрация
04.01.2021
Сообщения
78
Благодарностей
112
Баллы
33
Просто пушка. Благодарю :bp: мой голос за тебя!
 
  • Спасибо
Реакции: stud
Регистрация
23.03.2015
Сообщения
1 222
Благодарностей
764
Баллы
113
Я этого дождался! :bp::bp::bp::bp:
 
  • Спасибо
Реакции: stud

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
  • Спасибо
Реакции: OlegR

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 794
Благодарностей
2 466
Баллы
113
Материал отличный!
Можете на коленке набросать код для отписки от всех каналов и чатов?
 
  • Спасибо
Реакции: adr1enette и stud

OlegR

Client
Регистрация
11.06.2015
Сообщения
244
Благодарностей
250
Баллы
63
в многопотоке комфортно (в плане бана) работать по этому апи с телеграмм?
 
Последнее редактирование:

soprano

Client
Регистрация
25.08.2011
Сообщения
866
Благодарностей
948
Баллы
93

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 794
Благодарностей
2 466
Баллы
113
И для массовой рассылки, пожалуйста, заодно.
Мне не интересны рассылки.
Когда-то в разных аирдропах участвовал, завалился весь телеграм не нужными чатами и каналами.
Подумал, что человеку, который разбирается в этой библиотеке написать 15-20 строчек кода будет намного быстрее, чем мне изучить библиотеку с нуля.
Но, если это действительно настолько сложно - то на досуге разберусь самостоятельно.
 
  • Спасибо
Реакции: soprano

sergio197675

Client
Регистрация
21.09.2019
Сообщения
360
Благодарностей
318
Баллы
63
Подскажите , пжлста , как долго живут сессии созданные описанным методом , есть ли "подводные камни" приводящие к разавтаризации ( из опыта чего лучше не делат/делать для этого)?
Что лучше получить свою " пару" для белого проекта , или проще ( стоит ли вообще ) использовать купленные?
 
  • Спасибо
Реакции: stud

Sanekk

Client
Регистрация
24.06.2016
Сообщения
999
Благодарностей
390
Баллы
63
Приветствую. как здесь можно настроить работу через прокси? в самом апи такая возможность есть?
это скорее нужно в доках к библиотеке смотреть.
Материаль зачётный автору +
 

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
в многопотоке комфортно (в плане бана) работать по этому апи с телеграмм?
в рамках одного аккаунта - нет
многопоток нормально работает параллельно с несколькими аккаунтами
 

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
Материал отличный!
Можете на коленке набросать код для отписки от всех каналов и чатов?
там далеко не 20 строк), если обрабатывать все возможные варианты ошибок

давайте покажу пример запроса, на примере типа Channel - куда входят каналы и супергруппы, и кода из статьи, где мы уже получили диалоги аккаунта
ProjectMaker_2022-05-23_18-04-17.jpg

C#:
var channels = dialogs.Chats.OfType<TeleSharp.TL.TLChannel>();
foreach (TeleSharp.TL.TLChannel channel in channels)
{
    if (channel.Left)
        continue;

    project.SendInfoToLog("Отписываемся от канала: " + channel.Username);

    // Запрос отписаться от канала/супергруппы
    var req = new TeleSharp.TL.Channels.TLRequestLeaveChannel
    {
        Channel = new TeleSharp.TL.TLInputChannel
        {
            AccessHash = channel.AccessHash.Value,
            ChannelId = channel.Id
        }
    };
    var resultLeave = client.SendRequest<TeleSharp.TL.TLUpdates>(req);
}
 

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
Подскажите , пжлста , как долго живут сессии созданные описанным методом , есть ли "подводные камни" приводящие к разавтаризации ( из опыта чего лучше не делат/делать для этого)?
Что лучше получить свою " пару" для белого проекта , или проще ( стоит ли вообще ) использовать купленные?
сессии живут довольно долго, надо конечно осознавать что делаешь, и в лоб не долбить телегу запросами. она этого не любит. нужно расставлять разумные паузы/задержки.
По парам - тут отдельная история, у всех пар, можно сказать есть свой траст.
Самые трастовые - пары от оф. приложений), но и работать там надо осмысленнее.
 
  • Спасибо
Реакции: sergio197675

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 794
Благодарностей
2 466
Баллы
113
там далеко не 20 строк), если обрабатывать все возможные варианты ошибок

давайте покажу пример запроса, на примере типа Channel - куда входят каналы и супергруппы, и кода из статьи, где мы уже получили диалоги аккаунта
Посмотреть вложение 92198

C#:
var channels = dialogs.Chats.OfType<TeleSharp.TL.TLChannel>();
foreach (TeleSharp.TL.TLChannel channel in channels)
{
    if (channel.Left)
        continue;

    project.SendInfoToLog("Отписываемся от канала: " + channel.Username);

    // Запрос отписаться от канала/супергруппы
    var req = new TeleSharp.TL.Channels.TLRequestLeaveChannel
    {
        Channel = new TeleSharp.TL.TLInputChannel
        {
            AccessHash = channel.AccessHash.Value,
            ChannelId = channel.Id
        }
    };
    var resultLeave = client.SendRequest<TeleSharp.TL.TLUpdates>(req);
}
Этого более чем достаточно! Спасибо за помощь!
 
  • Спасибо
Реакции: stud

russya

Client
Регистрация
08.07.2014
Сообщения
745
Благодарностей
78
Баллы
28
круто! с меня +
 
  • Спасибо
Реакции: stud
Регистрация
23.03.2015
Сообщения
1 222
Благодарностей
764
Баллы
113
  • Спасибо
Реакции: stud

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Воу! Отличная статья, всё достаточно понятно расписано, спасибо за годный материал:-)
 
  • Спасибо
Реакции: stud

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
Объясните чайнику, к диалогам относятся обычные переписки? или только чаты и каналы?
да, в диалогах содержится вся инфа, которая отображается в клиенте.
давайте на примере разберем диалоги, в самом простом варианте, которые мы запросили в статье
Допустим, нам вернулся объект messages.dialogs
chrome_2022-05-24_22-43-36.jpg

dialogs - коллекция диалогов
messages - коллекция последних сообщений для диалогов
chats - коллекция с информацией о группах/каналах
users - коллекция с информацией о юзерах

Все, что у нас в клиенте отображается слева в колонке - это коллекция объектов Dialog
2022-05-24_22-47-46.jpg

2022-05-24_22-58-59.jpg

В коллекции messages - хранятся последние сообщения, которые отображаются под тайтлом диалога
2022-05-24_23-01-58.jpg

В коллекции chats - хранятся уже развернутая информация о группах/каналах, из которых берет скажем тайтлы
В коллекции users - хранятся уже развернутая информация о юзерах, из которых берет имя/фамилию
2022-05-24_23-08-17.jpg

В свойстве dialogs хранится, допустим только объекты dialog (TeleSharp.TL.TLDialog), и там хранится как-бы общая информация, например: закреплен ли диалог, с кем диалог (Peer), ID последнего сообщения, число не прочитанных сообщений и т.п.
а вся остальная информация, берется из расширенной информации самих объектов Chat и User

как пример, разбора диалогов с юзерами:
C#:
// Получаем диалоги только с юзерами
var dialogUsers = dialogs.Dialogs.OfType<TeleSharp.TL.TLDialog>().Where(x => x.Peer is TeleSharp.TL.TLPeerUser);
project.SendInfoToLog("Диалогов с юзерами: " + dialogUsers.Count());

// Перебираем диалоги и достаем расширенную инфу по ним
foreach (var dialogUser in dialogUsers)
{
    var dialogUserPeer = (TeleSharp.TL.TLPeerUser)dialogUser.Peer;
    // Получаем юзера из Users, согласно нашему диалогу. Ищем по Id Peer'a
    var user = dialogs.Users.OfType<TeleSharp.TL.TLUser>().FirstOrDefault(x => x.Id == dialogUserPeer.UserId);

    if (user != null)
    {
        // Ищем его последнее сообщение
        var messageUser = dialogs.Messages.OfType<TeleSharp.TL.TLMessage>().Where(x => x.PeerId is TeleSharp.TL.TLPeerUser).Where(x => ((TeleSharp.TL.TLPeerUser)x.PeerId).UserId == user.Id).FirstOrDefault(x => x.Id == dialogUser.TopMessage);

        if (messageUser != null)
        {
            // Готовим сообщение
            var textMessage = messageUser.Message.Replace("\n", " ".Trim());
            if (textMessage.Length > 29)
                textMessage = textMessage.Substring(0, 29) + "..."; // Обрезаем длинное сообщение

            // Готовим дату сообщения
            var dateMessage = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc).AddSeconds(messageUser.Date).ToLocalTime();

            // Формируем строку вывода
            var resultText = String.Format("Диалог юзера: {0} {1}. Не прочитано сообщений: {2}. Дата сообщения: {3}. Превью последнего сообщения: {4}", user.FirstName, user.LastName, dialogUser.UnreadCount, dateMessage.ToString("g"), textMessage);
            project.SendInfoToLog(resultText);
        }
    }
}
 
Регистрация
23.03.2015
Сообщения
1 222
Благодарностей
764
Баллы
113

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33

Вложения

Регистрация
23.03.2015
Сообщения
1 222
Благодарностей
764
Баллы
113
Спасибо сработало, буду дальше разбираться
 
  • Спасибо
Реакции: stud

Shytov

Client
Регистрация
11.09.2018
Сообщения
175
Благодарностей
39
Баллы
28
Так либа же мёртвая на половину, и глючная как постер на ранних версиях. В чем смысл пинать зомби
 

devffy

Client
Регистрация
16.03.2019
Сообщения
541
Благодарностей
188
Баллы
43
Классная статья. А можно ли реализовать удаление своих сообщений в определенном чате телеграм?(есть такая "апи-команда"?)
 
  • Спасибо
Реакции: stud

stud

Client
Регистрация
23.06.2013
Сообщения
88
Благодарностей
140
Баллы
33
Классная статья. А можно ли реализовать удаление своих сообщений в определенном чате телеграм?(есть такая "апи-команда"?)
Конечно можно. Через API работают все клиенты, даже официальные. Если можно что-то сделать в клиенте, это можно сделать и нашими запросами, в рамках конечно нашей версии.

C#:
// Выбираем нужную нам группу
string searchUsername = "usernameSuperGroup";
var getChat = dialogs.Chats.OfType<TeleSharp.TL.TLChannel>().FirstOrDefault(x => x.Username == searchUsername);

// Получаем историю сообщений этой группы
var requestHistory = new TeleSharp.TL.Messages.TLRequestGetHistory()
{
    Peer = new TeleSharp.TL.TLInputPeerChannel
    {
        ChannelId = getChat.Id,
        AccessHash = getChat.AccessHash.Value
    },
    Limit = 100,
};
var responseHistory = client.SendRequest<TeleSharp.TL.Messages.TLAbsMessages>(requestHistory);

if (responseHistory is TeleSharp.TL.Messages.TLChannelMessages)
{
    // Выбираем свои сообщения
    var historyMess = ((TeleSharp.TL.Messages.TLChannelMessages)responseHistory).Messages.OfType<TeleSharp.TL.TLMessage>().Where(x => x.Out);

    // Выбираем ID сообщений
    var historyMessId = historyMess.Select(x => x.Id);

    // Удаляем свои сообщения
    var requestDelete = new TeleSharp.TL.Channels.TLRequestDeleteMessages
    {
        Channel = new TeleSharp.TL.TLInputChannel
        {
            ChannelId = getChat.Id,
            AccessHash = getChat.AccessHash.Value
        },
        Id = new TeleSharp.TL.TLVector<int>(historyMessId)
    };

    var responseDelete = client.SendRequest<TeleSharp.TL.Messages.TLAffectedMessages>(requestDelete);
    project.SendInfoToLog("Удалили " + responseDelete.PtsCount + " сообщений");
}
 
Последнее редактирование:
  • Спасибо
Реакции: devffy

lzlmrf

Client
Регистрация
14.08.2015
Сообщения
488
Благодарностей
149
Баллы
43
  • Спасибо
Реакции: AleXPrischepA

lzlmrf

Client
Регистрация
14.08.2015
Сообщения
488
Благодарностей
149
Баллы
43
Перейдем к делу! Для работы с любым API, требуется по крайней мере api ключ, который выдается поставщиком API. В Телеграм, для работы с API используется одновременно – два ключа: Api_ID и Api_Hash, получить которые можно на странице создания своего приложения
вот тут уже затык. не получается получить пару, ERROR. Не подскажете как решить?
 

OlegR

Client
Регистрация
11.06.2015
Сообщения
244
Благодарностей
250
Баллы
63
В нашей версии библиотеки версия API статична и адаптирована под версию 133. Поэтому мы будем ориентироваться на нее, и для этого нам необходимо зайти в документацию, выбрать любой метод, и установить нужный на Layer на 133.
Например зайдем в метод auth.sendCode и изменим Layer 139 на 133, и далее при сёрфинге по всей документации версия будет отображаться выбранная нами:
как сделать (или где взять) статическую библиотеку под 139 Layer?
 

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)