yaroslavche / phptdlib

PHP Extension for tdlib/td written with PHP-CPP
https://yaroslavche.github.io/phptdlib/
MIT License
103 stars 26 forks source link

Авторизация и интеграция #53

Closed trueSiberian closed 4 years ago

trueSiberian commented 4 years ago

Доброго времени суток!

  1. Если возможность авторизавать без кода подтверждения с помощью PUBLIC KEY.

  2. Взял пример с https://yaroslavche.github.io/phptdlib/documentation.html (TDLib\JsonClient)

Запускаю php ../php_examples/test.php

Ответ: [32]=> string(266) "{"@type":"authorizationStateWaitCode","code_info":{"@type":"authenticationCodeInfo","phone_number":"7XXXXXXXXXX","type":{"@type":"authenticationCodeTypeSms","length":5},"next_type":{"@type":"authenticationCodeTypeCall","length":0},"timeout":120},"@extra":1957747793}" [33]=> string(72) "{"@type":"error","code":401,"message":"Unauthorized","@extra":424238335}"

Что с этим можно сделать?

  1. и как получить доступ из другой папки сайта не понял, пытался через use не нашел namespace. из консоли скрипт хотя бы начинает работать, когда через браузер, пише нет таких классов

Подскажите пожулуста)

radmirr commented 4 years ago

Авторизацию достаточно пройти 1 раз добавив в свой скрипт обработку событий авторизации (updateAuthorizationState), т.е. шаги "authorizationStateWaitTdlibParameters"->"authorizationStateWaitPhoneNumber"->"authorizationStateWaitCode"->"authorizationStateReady". Далее при запуске скрипта будет достаточно "скормить" параметры на событии "authorizationStateWaitTdlibParameters" и начать слушать события. И вы уверены, что вам нужно не что-то вроде https://github.com/evgeny-nadymov/telegram-react ?

yaroslavche commented 4 years ago

Клиент в любом случае будет ждать параметры и авторизацию. Как верно заметил @radmirr , достаточно пройти один раз. Но нужно иметь ввиду, что авторизация рано или поздно может "слететь". По этому крайне желательно (я бы даже сказал - обязательно) проверять с помощью getAuthorizationState. Если вернёт authorizationStateReady:

The user has been successfully authorized. TDLib is now ready to answer queries.

Насчет паблик кей я ничего не подскажу, т.к. лично сам расширением не пользуюсь =) Возможно кто-то сможет подсказать. Но судя по Function Class Reference навряд ли.

trueSiberian commented 4 years ago

на счет PUBLIC KEY понял и про проверку авторизации, но как по итогу авторизироваться. Так как брал функцию из примера.

Я же правильно понимаю, при первом выполнении скрипта, должен придти код на телефон $client->setAuthenticationPhoneNumber($phone_number, 3); // wait response 3 seconds. default - 1.

а после это, мы комментируем получение кода,а полученный код вставляем ниже. $result = $client->query(json_encode(['@type' => 'checkAuthenticationCode', 'code' => 'xxxxx', 'first_name' => 'dummy', 'last_name' => 'dummy']), 10);

Но код не приходит, вот в чем беда.

DerAlSem commented 4 years ago

У тебя перед setAuthenticationPhoneNumber какой статус?

Должно быть так:

Начинаешь с этого: td_json_client_execute($client, json_encode(['@type' => 'getAuthorizationState']));

По идее, ответом приходит updateAuthorizationState. Смотришь @type.

На authorizationStateWaitTdlibParameters отвечаешь параметрами тдлиб.

Тебе опять прилетает updateAuthorizationState. Опять смотришь @type

Должен быть authorizationStateWaitEncryptionKey. Отвечаешь ему ключом.

Опять прилетает ответ с updateAuthorizationState и ты опять смотришь @type.

Если authorizationStateWaitPhoneNumber - то вот тогда-то и даешь ему setAuthenticationPhoneNumber

И вот если все сработало, то тебе телега отправит код (на другой тг) и прилетит запрос authorizationStateWaitCode

И вот на него уже отвечаешь кодом.

yaroslavche commented 4 years ago

Я же правильно понимаю, при первом выполнении скрипта, должен придти код на телефон $client->setAuthenticationPhoneNumber($phone_number, 3); // wait response 3 seconds. default - 1

Да, всё правильно. Но код должен придти. Не приходит на указанный номер? Значит что-то не так. Нужен лог из консоли, тот что тдлиб. Для этого в строке из примера из документации нужно указать LVL_ALL вместо LVL_ERROR.

\TDApi\LogConfiguration::setLogVerbosityLevel(\TDApi\LogConfiguration::LVL_ALL);

В этом случае лог будет как примерно тут (в самом конце). Но не забудь удалить из лога айди и ключ апи и телефон =) И сам лог желательно скинуть используя это (так как там должно быть много чего, тут поедет).

А в целом, @DerAlSem описал действия, как оно должно работать с обычными td_json_client_... функциями. То что в примере - просто "обёртка" на этими функциями.

yaroslavche commented 4 years ago

td_json_client_execute($client, json_encode(['@type' => 'getAuthorizationState']));

@DerAlSem я не уверен на 100%, но разве getAuthorizationState не обычным td_json_clinet_send вызывается?

trueSiberian commented 4 years ago

Сейчас ошибок нет, но код все равно не приходит. [30]=> string(306) "{"@type":"updateAuthorizationState","authorization_state":{"@type":"authorizationStateWaitCode","code_info":{"@type":"authenticationCodeInfo","phone_number":"+7XXXXXXXXXX","type":{"@type":"authenticationCodeTypeSms","length":5},"next_type":{"@type":"authenticationCodeTypeCall","length":0},"timeout":120}}}" [31]=> string(34) "{"@type":"ok","@extra":1714636915}"

Вот лог https://pastebin.com/B9Squ4vx

trueSiberian commented 4 years ago

и ввиду того, что я не имел опыта работы с подобными extension. направьте как это потом можно интегрировать в yii2 и laravel.

еще все развертуто локально и стоит telegram-desktop для Ubuntu. Я просто уже не знаю в чем проблема может быть.

radmirr commented 4 years ago

Судя по всему, вы не сообщаете телеграму код - как только приходит событие "authorizationStateWaitCode" телеграм начинает ждать код подтверждения (он приходит в другой клиент телеграма или по СМС), как только это событие поступило, нужно с помощью функции "checkAuthenticationCode" передать этот код. Например, $this->client->send(json_encode(['@type' => 'checkAuthenticationCode', 'code' => $code])); , где $code это код из сообщения.

trueSiberian commented 4 years ago

Так в том то и дело, что код никуда не приходит

после $client->setAuthenticationPhoneNumber($phone_number, 3); все без ошибок, и код не приходит

radmirr commented 4 years ago

Выставьте в параметрах библиотеки параметр TDApi\TDLibParameters::USE_TEST_DC в значение false (у вас он в true), в тестовом инстансе код просто так не придет, там еще и регистрацию необходимо правильно пройти.

trueSiberian commented 4 years ago

Пришло, я пару раз менял USE_TEST_DC, но смс не приходило, а сейчас пришло в телеграм на телефоне. Спасибо больное. МОжно еще пример попросить как отправлять сообщения То что попробвал я выдало ошибку {"@type":"error","code":5,"message":"Can't send message without content","@extra":1957747793}

$result = $client->query(json_encode(['@type' => 'sendMessage', 'chatid' => 'usernaem', 'input_messagecontent' => 'Если тебя это пришло, значит заработало']), 10);

и хотя направьте, как это интегрировать в Yii2 и Laravel

И еще раз большое спасибо

radmirr commented 4 years ago

Что-то вроде

$this->client->send(json_encode(['@type'=>'openChat','chat_id'=>$chat_id]));
$this->client->send(json_encode([
    '@type'=>'sendMessage',
    'chat_id'=>$chat_id,
    'reply_to_message_id'=>0, 
    'disable_notification'=>false,
    'from_background'=>false,
    'input_message_content'=>[
        '@type'=>'inputMessageText',
        'text'=>[
            '@type'=>'formattedText',
            'text'=>$message_text,
            'entities'=>[]
        ],
        'disable_web_page_preview'=>false,
        'clear_draft'=>false
    ],
    '@extra' => $extra
]));
$this->client->send(json_encode(['@type'   => 'closeChat', 'chat_id' => $chat_id])); 

где $chat_id - id чата в телеграме, $message_text - текстовое сообщение, $extra - поле для последующей идентификации ответа на запрос, можно не использовать. По вопросу интеграции с Yii2 и Laravel уже не смогу подсказать, т.к. использовал библиотеку для интеграции с совершенно другой системой.

yaroslavche commented 4 years ago

как это интегрировать в Yii2 и Laravel

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

yaroslavche commented 4 years ago

sendMessage

Выше уже привели пример, но еще раз упомяну как узнать, что надо отправлять:

  1. Ищем и смотрим в документации сам метод sendMessage. На этом этапе мы знаем @type:

    {"@type":"sendMessage"}
  2. У каждого метода в документации есть публичные поля (Public Fields). И если они не пустые, тогда это и есть дополнительные аргументы в запросе. В данном конкретном случае:

type key description
std::int64_t chatid Target chat.
std::int64_t reply_to_messageid Identifier of the message to reply to or 0.  
object_ptr options_ Options to be used to send the message.  
object_ptr replymarkup Markup for replying to the message; for bots only.
object_ptr input_messagecontent The content of the message to be sent.

Это и будут наши последующие ключи в массиве, который будет кодирован в результирующий json'е.

{"@type":"sendMessage","chat_id":123123123,"reply_to_message_id":0,"options":[],"reply_markup":[],"input_message_content":[]}

Так же замечу, что для ключей я удалил последний символ подчёркивания "_" Ну а тип подсказывает, чего ожидает тдлиб. Если это std::int64_t - очевидно, что нужно целое число. object_ptr - объекты определенного типа (как указано в дженерике, в данном случае sendMessageOptions, ReplyMarkup и InputMessageContent)

json_encode([
'@type' => 'sendMessage',
'chat_id' => 123123123,
'reply_to_message_id' => 0,
'options' => [/* смотрим sendMessageOptions Class Reference */],
'reply_markup' => [/* смотрим ReplyMarkup Class Reference */],
'input_message_content' => [/* смотрим InputMessageContent Class Reference */],
]);

Всё остальное в json api работает идентичным образом.

yaroslavche commented 4 years ago

'@extra' => $extra , $extra - поле для последующей идентификации ответа на запрос, можно не использовать.

Кстати, '@extra' всегда добавляется в запрос, если этот ключ не указан напрямую и используется \TDLib\JsonClient::query код. Собственно, именно таким способом отслеживается определенное сообщение, которое возвращается методом query

trueSiberian commented 4 years ago

Спасибо, сейчас буду пробовать разбираться дальше)

yaroslavche commented 4 years ago

@radmirr @DerAlSem @trueSiberian (и возможно еще кто-то прочитает и захочет =) ) так как вы уже прекрасно понимаете как работает tdlib json client, не могли бы вы помочь написать документацию, которая снизит количество подобных issue (которых множество, однотипны и в целом не очень-то и зависят от phptdlib, а от понимания самого tdlib)? Лучше на русском (потом уже и переведётся, улучшится.), т.к. основная масса пользователей - так или иначе понимающие русский. Я могу перевести то, что я писал тут. Но я не знаю как лучше объяснить правильно. Буду благодарен за помощь =) PRs welcome

trueSiberian commented 4 years ago

Я попробую немного позже, несколько примеров описать которые использую, но мне кажется это будет топорно)))

trueSiberian commented 4 years ago

Итого по интеграции все ок в laravel, просто с котроллере use \TDApi; use \TDLib;

а вот когда docker поднимаю, там класс не находит. разбираюсь

И как фото пользователя скачать, потому что возвращаются данные, типа скачено, а что и куда не понятно. [photo][ [remote]][is_uploading_completed] => 1

DerAlSem commented 4 years ago

Фото в сторейдж дир в тдлиб параметрах.

radmirr commented 4 years ago

"uploading_complete" это скорее всего отображение загружен файл на сервер или нет. Чтобы скачать файл себе наверно придется загружать его через https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1download_file.html

yaroslavche commented 4 years ago

а вот когда docker поднимаю, там класс не находит. разбираюсь

ну а в контейнере (где php) расширение собрано и включено? Его нужно включить и там. Что показывает php -m | grep tdlib?

yaroslavche commented 4 years ago

Inactive. Feel free to reopen