среда, 9 февраля 2022 г.

Использование Telegram Core API (MTProto) на PHP

Эта заметка не про Bot API, а про Core API Telegram, с помощью которого можно создавать полноценные клиенты для месседжера, и конечно же любой другой софт, например для сбора данных из Телеграма. Основная проблема заключается в том, что общение с серверами Telegram осуществляется по специальному протоколу разработанным внутри компании — MTProto. Именно благодаря этому протоколу данный месседжер и славится своей безопасностью и шифрование данных.

Вас мучают вопросы: как использовать Telegram Api на PHP? Как вызывать функции? Очень много примеров использования telegram api для бота, а как использовать обычное api telegram? Зарегистрировал приложение, получил api_id и api_hash, как получить все сообщения из телеграм-канала? https://core.telegram.org/method/messages.getHistory
Как вызвать этот метод? Как реализовать авторизацию с помощью API Telegram? Тогда эта статья для вас!

Естественно, разбирать нюансы протокола MTProto в данной заметке я не буду. Для работы с ним буду пользоваться PHP-библиотекой MadelineProto, доступной всем желающим на GitHub. Однако, нельзя просто так взять и воспользоваться библиотекой. Есть как минимум три нюанса, которые нужно решить.

Подготовка к установке MadelineProto

Во-первых, нужен установленный Python, будет достаточно версии 2.7.

Во-вторых, библиотека не помечена как стабильная, поэтому для подключения её через composer к существующему проекту нужно немного отредактировать composer.json:

"minimum-stability": "dev",

Для того, чтобы composer не ругался на отсутствие стабильных версий зависимостей. Без указания этой директивы во время установки библиотеки будет получена примерно такая ошибка:

Your requirements could not be resolved to an installable set of packages.

Problem 1
 - Installation request for danog/madelineproto ^2.0 -> satisfiable by danog/madelineproto[2.0].
 - danog/madelineproto 2.0 requires danog/primemodule dev-master -> satisfiable by danog/primemodule[dev-master] but these conflict with your requirements or minimum-stability.


Installation failed, reverting ./composer.json to its original content.

Затем нужно указать git-репозиторий библиотеки:

"repositories": [
    {
        "type": "git",
        "url": "https://github.com/danog/phpseclib"
    }
],

и только затем можно устанавливать саму либу:

composer require danog/madelineproto

Если во время установки зависимостей появится ошибка на подобии такой:

github Failed to clone via https, ssh protocols, aborting.
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version

То вам нужно обновить версию git.

Регистрация приложения для Telegram API

Теперь нужно зарегистрировать приложение в разделе API development tools и получить App api_id и App api_hash.

Как правильно использовать MadelineProto с Laravel

В-третьих, на сегодняшний день (2017-02-10) мне не удалось запустить MadelineProto из коробки, т.к. начинали сыпаться ошибки типа:

DataCenter: Connecting to DC 2 (main server, ipv4, tcp_full)...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 443...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 80...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 88...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 443 without the proxy...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 80 without the proxy...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
DataCenter: Connection failed, retrying connection on port 88 without the proxy...
Exception: stream_set_timeout() expects parameter 1 to be resource, null given in Socket.php:153
Exception: Undefined offset: 2 in MsgIdHandler.php:77
CallHandler: An error occurred while calling method help.getNearestDc: Undefined offset: 2 in MsgIdHandler on line 77. Recreating connection and retrying to call method...
Exception: Undefined offset: 2 in MTProto.php:641

In MTProto.php line 641:

Undefined offset: 2

На самом деле здесь нет ничего фатального, просто фреймворк Laravel по-умолчанию перехватывает все ошибки и при отсуствии должных обработчиков завершает скрипт даже при наличии не критичных ошибок. Возможно такое поведение присутствует и в других фреймворках. Можно изменить уровень ошибок, добавив в метод \App\Providers\AppServiceProvider::boot() строку:

error_reporting(0);

Но тогда есть вероятность пропустить некритичные ошибки своего приложения.

Вторым способом устранения ошибок будет правка исходника /vendor/danog/madelineproto/src/danog/MadelineProto/Connection.php, а именно нужно закомментировать 3 строки в конструкторе в условии

case 'tcp_full':
//                $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout);
//                $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout);
//                $this->sock->setBlocking(true);

В коммите 56c0d431768c04009ae9aa3151715b5e6399ec4d эти строки находятся на 105-107 строках файла. Источник проблемы был найден с помощью отладчика xDebug. Проблема заключалась в том, что методы $this->sock->setOption() и  $this->sock->setBlocking() пытались работать с ещё не созданным объектом $this->sock->sock. Если у вас возникнут другие ошибки, то с помощью отладчика вы их легко обнаружите и исправите.

Также в библиотеку могут быть зашиты устаревшие или не актуальные IP-адреса серверов Телеграма. Их всегда можно посмотреть на странице API development tools и передать в ModelineProto через конструктор \danog\MadelineProto\API().

Список всех параметров которые можно изменить в этой библиотеке можно посмотреть в массиве $default_settings метода \danog\MadelineProto\MTProto::parse_settings().

В идеале нужно зарегистрировать для приложения новую чистую учётную запись, но для тестирования и отладки вполне сгодится любая уже имеющаяся учётка Телеграма.

Пример работы MadelineProto на Laravel

Как делать запросы к Telegram API на PHP?

Приведу простой пример кода на базе консольной команды для Laravel:

public function handle() {

        // Если файл с сессией уже существует, использовать его
        if(file_exists( env('TELEGRAM_SESSION_FILE') ) ) {
            $madeline = new API( env('TELEGRAM_SESSION_FILE') );
        } else {
        // Иначе создать новую сессию
            $madeline = new API([
                'app_info' => [
                    'api_id' => env('TELEGRAM_API_ID'),
                    'api_hash' => env('TELEGRAM_API_HASH'),
                ]
            ]);

            // Задать имя сессии
            $madeline->session = env('TELEGRAM_SESSION_FILE');

            // Принудительно сохранить сессию
            $madeline->serialize();

            // Начать авторизацию по номеру мобильного телефона
            $madeline->phone_login( env('TELEGRAM_PHONE') );
            // Запросить код с помощью консоли
            $code = readline('Enter the code you received: ');
            $madeline->complete_phone_login($code);
        }

        $messages = $madeline->messages->getHistory(['peer' => '@ANY_CHANNEL_ID', 'offset_id' => 0, 'offset_date' => 0, 'add_offset' => 0, 'limit' => 10, 'max_id' => 0, 'min_id' => 0, 'hash' => 0, ]);

        foreach($messages['messages'] as $msg) {
            dump($msg);
        }

    }

Для тех, кто не умеет в Laravel, кратко поясню. Вызовы env() — это запросы значений из файла конфигурации, можно заменить их на константы или захардкодить. Собственно:

TELEGRAM_SESSION_FILE — любое значение, которое можно использовать в качестве имени файла.

TELEGRAM_API_ID и TELEGRAM_API_HASH — Данные из API development tools.

TELEGRAM_PHONE — мобильный номер существующий учётки, например, +7XXXXXXXXXX.

Теперь пояснения о происходящем в коде. Сессия — достаточно важный объект клиента, без него при каждом запуске скрипта авторизовываться и вводить код из сообщения, который Telegram высылает либо в смс либо через сам месседжер. Также на этапе авторизации происходит вся знаменитая шифровочная телеграм-магия. Процесс не быстрый, на моём тестовом стенде он мог затягиваться на минуты.

В результате работы скрипта в консоль будет выведено огромное количество отладочной информации, на которую можно не обращать внимания. При первом запуске сессии нужно будет авторизоваться в месседжере:

API: Running APIFactory...
API: MadelineProto is ready!
API: Serializing MadelineProto...
Login: Sending code...
Login: Code sent successfully! Once you receive the code you should use the complete_phone_login function.
Enter the code you received: ...
Login: Logging in as a normal user...
MTProto: Trying to copy authorization from dc 2 to dc 1
MTProto: Trying to copy authorization from dc 2 to dc 3
MTProto: Trying to copy authorization from dc 2 to dc 4
ResponseHandler: Parsing updates received via the socket...

После чего можно полноценно использовать все возможности Telegram Core API, например,  $messages = $madeline->messages->getHistory().

Данный метод возвращает сообщения из канала в обратном хронологическом порядке, т.е. начиная с самых свежих. Подробнее о параметрах этого метода можно узнать на страницах официальной документации MadelineProto. Заметьте, параметры MadelineProto могут отличаться от параметров официальной документации самого Telegram.

Отблагодарить можно через форму справа "Donate" ... )

To reward you via the form on the right "Donate" ... )

:)

вторник, 1 февраля 2022 г.

Пакеты Flutter, которые я использую в каждом проекте


В этой статье я просто хочу познакомить новых пользователей с моими любимыми пакетами.

Речь пойдет о некоторых из лучших пакетов Flutter, которые могут сократить время разработки и повысить производительность вашего приложения Flutter в кратчайшие сроки.

Эти пакеты и библиотеки Flutter используются для различных аспектов технологии Flutter. Итак, давайте с них начнем.

Управление состоянием

Я считаю, что riverpod — это самое прекрасное решение для управления состоянием.

Оно быстрое, надежное, совершенное. Ниже перечислены причины, по которым стоит выбрать Riverpod:

  • Он не зависит напрямую от Flutter SDK.

  • Riverpod можно использовать для создания и обеспечения однонаправленного потока данных с классами моделей, которые являются иммутабельными (то есть они не меняются).

  • Riverpod не зависит напрямую от дерева виджетов; его работа похожа на работу локатора служб. Провайдеры объявляются глобально и могут быть использованы в любом месте приложения

  • отлавливает ошибки программирования во время компиляции, а не во время исполнения

  • устраняет вложенность для прослушивания/комбинирования объектов

  • обеспечивает тестируемость кода

  • поддержка автоудаления

  • сравнение предыдущего и нового состояния

  • реализует механизм отмены-повторения (undo-redo)

  • отладка состояния приложения

Читайте мое руководство для riverpod.

Чистый код

flutter_hooks дает нам гораздо более чистый код и избавляет нас от бойлерплейт-кодов, обрабатывая их все за нас.

Вы можете ознакомиться с моей статьей о хуках, чтобы воспользоваться некоторыми идеями.

Формы

Я использую его для создания более четких и качественных форм flutter. Это помогает нам избавиться от большого количества бойлерплейт-кода.

Также у меня есть статья об этом пакете.

Моделирование

Классы данных в Dart — отстой. Потому что вам нужно вручную обрабатывать такие функции, как toJson-fromJson, они мутабельны и много чего еще.

Такие решения, как JSON to Dart и quicktype, дают нам лишь ограниченную конфигурацию и кастомизацию.

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

Это json_serializable и freezed

  • json_serializable помогает конвертировать наши модели в JSON или наоборот.

  • freezed также помогает создавать иммутабельные классы, что повышает надежность наших моделей.

JSON Serializable + Freezed - это идеальный вариант. С вашими моделями теперь не будет никаких проблем.

HTTP-клиент

dio намного лучше, чем пакет http.

Потому что он имеет интерцепторы и расширенные возможности, плагины cache_interceptor, pretty_dio_logger, cookie_manager; также можно создавать свои собственные интерцепторы.

Анимации

Lottie — это упрощенный пакет для создания анимации. Вы можете создавать анимацию в Adobe After Effects и легко анимировать на Flutter. Он быстрый и легкий, поэтому можно не беспокоиться о вероятных проблемах с памятью и процессором. Это сделает ваше приложение гораздо более удобным для пользователя.

Также вы можете найти множество анимаций здесь.

Хранилище

shared_preferences в порядке, но он медленный и очень ограниченный, слишком примитивный и переоцененный.

Я использую в основном пакет hive, но сейчас полюбил objectbox

  • Прост в использовании

  • Довольно быстрый

  • Безопасен (расширенная поддержка шифрования)

  • Работает не только с примитивами, также поддерживает и сложные объекты

  • Даже быстрее hive и поддерживает автоматическую синхронизацию данных между устройствами

I18N И L10N (Интернационализация и локализация)

Если ваше приложение многоязычное, то intl просто необходим, потому что он оказывает большую помощь в решении проблем локализации, таких как:

  • Часовые пояса

  • Временные форматы 

  • Форматы чисел

  • Форматы валют

  • Множественные числа и гендерные особенности …

Продакшн-хелпер

Вам не нужно обрабатывать все нативные коды и файлы.

Создайте нативную заставку всего одной командной строки.

Создайте иконки запуска каждого устройства с помощью всего одной волшебной команды. Для получения подробной информации ознакомьтесь с этой статьей.

Навигация и утилиты

GetX имеет довольно хорошую систему навигации и множество полезных функций.

  • Простота использования

  • Навигация без contex

  • Поддержка динамических URL

  • Поддержка промежуточного программного обеспечения

  • Также обладает таким количеством дополнительных функций, что я не в состоянии их все перечислить.

Подробнее прочитать можно здесь.

Также я использую это решение для управления состоянием и внедрения зависимости, но только для средних и небольших проектов.

Лучший UI/UX опыт 

Почему не нижний лист (bottom sheet) по умолчанию?

  • Он гораздо удобнее для пользователя

  • Возможность просмотра с внутренней прокруткой + перетаскивание вниз для закрытия

  • Поддержка нативного нижнего листа в виде стопки

  • Хорошо кастомизируемый

Пакет flash - это как швейцарский армейский нож. Он отлично кастомизируется и чрезвычайно мощный.

Я использую его для диалоговых окон, снекбаров и тостов.

Он хорошо кастомизируемый и гораздо более удобный для пользователя

Автоматическое кэширование изображений и профессиональная обработка изображений.


Материал подготовлен в рамках курса «Flutter Mobile Developer».

Всех желающих приглашаем на бесплатный двухдневный интенсив «Flutter engine, анимация и ее оптимизация». На интенсиве мы рассмотрим самые глубокие механизмы Flutter Engine и научимся создавать сложные и плавные анимации как на мобильных платформах, так и веб-версии, использовать инструменты профилирования для исключения "замерзания" интерфейса. Также мы затронем тему использования WebGL в веб-приложениях на Flutter для создания трехмерных сцен. Регистрация здесь.

Отблагодарить можно через форму справа "Donate" ... )

To reward you via the form on the right "Donate" ... )

:)

друзья )

Сохраняйте и делитесь желаниями, и не забывайте о важных датах! парсинг центр