Почему это вообще появилось здесь?

Недавно я написал статью о разработке бота на php с использование laravel+botman для telegram. Самое первое, что написали, цитирую, “стрельба из пушки по воробьям”. Я согласен с этим, даже осознавал это во время разработки, но мне был интересен laravel.

image

Сейчас же я разрабатывал бота на чистом php(без обвязок) и API telegram, а так как статей на подобную тему очень много, то плюсом немного затронем API google(api youtube). Надеюсь, вам будет интересно и полезно узнать о API youtube.

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

Постановка задачи


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

В принципе, функционал довольно простой, но как работать с youtube? Оказывается решение этой задачи есть у самого google и имя ему google API. Он позволяет работать со всеми приложениями от компании, но меня интересовал лишь youtube.

Настройка и разработка


Так получилось, что во время изучения api youtube было найдено куда элегантное решение моей задачи, его предложила сама документация по api. Но сначала о api. Чтобы начать работать с ним вам необходимо перейти в google console и выбрать нужный вам вариант api. После чего путь лежит лишь в документацию или на stackoverflow. Сразу скажу, русского варианта документации нет, уроков тоже нет. Желательно иметь минимальные знания английского языка или действовать методом тыка.

Выглядит это так. Вы заходите в google console, создаете свой проект и выбираете нужный API.

image

А теперь к решению проблемы. Во время чтения документации я нашел(google сам показал) сервис pubsubhubbub.appspot.com/subscribe он позволяет связать youtube и ваше приложение. Как работает? Работает по принципу webhook. Вы вставляете youtube канала, который хотите прослушать и каждый раз при каких либо действиях на канале(добавление видео, удаление, изменение) будите получать данные на свой скрипт.

image

Callback URL — скрипт, который будет принимать данные от google.
Topic URL — канал, который вы хотите прослушивать.

Ну и поле Mode позволяет выбрать, что вы хотите, подписаться или отписаться от прослушивания.

Приступим к написанию кода, для начала давайте настроим наш скрипт для работы с youtube. Я писал все в одном файле т.к. это был тест + кода там действительно мало. После того, как вы отправите запрос на подписку его нужно подтвердить. Погуглив, можно найти ответ на всеми любимом сайте, один из комментариев на stackoverflow подсказывает.

$video = "null";

if (isset($_GET['hub_challenge'])) { echo $_REQUEST['hub_challenge']; } 
else { $video = parseYoutubeUpdate(file_get_contents('php://input')); }

function parseYoutubeUpdate($data) {
    $xml 		= simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
    $video_id 	= substr((string)$xml->entry->id, 9);
    $channel_id = substr((string)$xml->entry->author->uri, 32);
    $published  = (string)$xml->entry->published;

    return array(
        'video_id'=>$video_id,
        'channel_id'=>$channel_id,
        'published'=>$published 
    );
}

Здесь мы создаем для удобства переменную в которой будет нужная нам инфа о видео. Две последующие строки, позволяют определить, есть ли возможность подтвердить запрос от pubsubhubbub, если да, то подтверждаем, если нет, то значит, что пришли данные от youtube и нам нужно их обработать. В функции parseYoutubeUpdate мы обрабатывает ответ, получаем всю нам нужную инфу.

Здесь стоит сделать отступление и рассказать о особом(на мой взгляд, могу ошибаться) виде данных, которым пользуется youtube(для ответов) он называется, как я понял, atom(не путать с IDE или это обычный xml… опыта с ним было мало). Выглядит он как-то так(небольшой кусок ответа от youtube):

<id>yt:video:eE5mpblYpdY</id>
 <yt:videoId>eE5mpblYpdY</yt:videoId>
 <yt:channelId>UCGqKr3O5ub-O7zEKx_qeHUQ</yt:channelId>
 <title>20b3560a49 1080</title>
 <link rel="alternate" href="https://www.youtube.com/watch?v=hgCQ378xNus"/>
 <author>
  <name>not Epic</name>
  <uri>https://www.youtube.com/channel/UCGqKr3O5ub-O7zEKx_qeHUQ</uri>
 </author>
 <published>2019-07-14T05:10:49+00:00</published>
 <updated>2019-07-14T05:11:07.600177664+00:00</updated>

Вернемся к parseYoutubeUpdate().

В функции мы преобразуем ответ в xml формат.
Записываем в переменные нужные нам данные.
А после возвращаем массив с этими данными.

Переходим к telegram. Для начала хочется сказать, это ****** как легче работать нежели с botman. Если вы хотите разрабатывать ботов только под telegram, то не пользуйтесь библиотеками, которые позволяют разрабатывать ботов под разные платформ…. в этом нет смысла… больше проблем будет. API telegram'a очень понятное и простое даже для новичка, который только познакомился с php и имеет минимальные знания ООП.

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

const TOKEN = "6826815*******Yme99*****9kjzgVi*****3S******";
$url = 'https://api.telegram.org/bot' . TOKEN . '/sendMessage';

Теперь нам необходимо лишь отправить запрос на сервера telegram.

$params = [
	'chat_id' =>712531723,
  	"text" => $linkVideo,
];

$url = $url . '?' . http_build_query($params);

Создаем необходимые параметры, для меня это id чата(если выводит на продакшен бота, то необходимо сохранять все id в БД чтобы спамить) и текстовое сообщение.

Как вы могли заметить, я передаю ссылку как простое сообщение, а не видео. Как я понял, телеграм передает видео лишь в том случае, если оно загружено на сервер, а иначе нет… + Мне необходимо видеть превью картинку для видео.

Теперь наш бот будет получать уведомления о выходе/редактирование видео. Выглядит это как-то так:

image

Game over. У меня все на этом. Самый большой недостаток этого кода в том, что он находится в одном файле, но кода на 10 строк для меня не имела смысла разделять.

Исходники — github.

Комментарии (13)


  1. kruslan
    11.08.2019 18:49
    -2

    if (isset($_GET['hub_challenge'])) { echo $_REQUEST['hub_challenge']; } 
    else { $video = parseYoutubeUpdate(file_get_contents('php://input')); }
    


    Жесть какая… Лет 10 такого не видел.


    1. EpicLegend_gg Автор
      11.08.2019 19:16
      +2

      В каком плане?


      1. demonarxs1
        11.08.2019 21:18

        Он про качество кода… Уделите внимание мелочам… У Вас результат вызова функции передается в аргумент функции… Это можно вынести, и будет лучше. Затем, можно вынести условие… и сделать не однострочный if/else…
        Уделите внимание мелочам. Наверно это подразумевалось.


    1. Dromok
      11.08.2019 20:32
      +1

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


      1. vn_sten
        12.08.2019 07:10

        Если для вас это «обычный подход», то вы сильно отстали от современного php.
        Такой пример кода сойдёт показать другу, но не выкидывать на хабр


        1. EpicLegend_gg Автор
          12.08.2019 07:12

          В плане производительности есть разница? Если нет, то здесь вопрос лишь в читаемости, а эти споры никогда не закончатся.


    1. Rastishka
      11.08.2019 20:36
      +2

      А как сейчас принято писать условия?


      1. Vitaly48
        12.08.2019 07:10

        1. Rastishka
          13.08.2019 02:48

          А, тогда согласен.
          А то я думал эта дурь medium.com/edge-coders/coding-tip-try-to-code-without-if-statements-d06799eed231 добралась и до PHP.


  1. BogdanH
    12.08.2019 10:36

    Чего вас так задевает, для написания скрипта в личном проекте автор может писать, КАК ЕМУ УГОДНО. Хабр — не коммисия по чистому коду, логика показана, подход показан, можете взять пример и написать по своему.

    Автор, а API предостовляет доступ к комментам под видео?


    1. EpicLegend_gg Автор
      12.08.2019 10:38

      API возможно, а вот сервис pubsubhubbub нет. Из API можно получить все данные о видео(как в админ панели youtube канала), но вот про комменты я не уверен.


  1. dron88
    12.08.2019 10:38

    Уважаемые коллеги, а может кто подобное на Python делал или встречал. Задача 1 в 1, написать смогу сам, но мало ли есть готовое решение, тем более я только учу Python.
    P.S. Автору спасибо за идею.


    1. EpicLegend_gg Автор
      12.08.2019 10:40

      Если только учишь, то лучше сам напиши, встретишь много нового. Если юзать библиотеку, то много упустишь. Работать будет, но не понятно как. =)
      Сам так laravel изучал.