Получение сообщений из трансляций youtube + авторизация google на PHP

в 11:33, , рубрики: Google, Google API, php, youtube api

На днях встала задача получения сообщений из стрима youtube. Статей по этому поводу не нашел, а есть лишь офф. документация гугл. С ней я разобрался (надеюсь) и готов поделиться с вами опытом.

image

Первое, что я нашел — это метод LiveChatMessages: list, казалось бы, все просто, но обязательным параметром требуется передать liveChatId, который вы можете получить сделав запрос на LiveBroadcasts: list, но что бы сделать туда запрос необходимо авторизовать пользователя через google с доступом на чтение аккаунта. В примерах все подробно прописано, но если вы читаете эту статью, возможно, не так уж и понятно как хотелось бы.

Авторизация

Консоль гугл

Using OAuth 2.0 for Web Server Applications, хочу сразу заметить, требуется именно Web Server авторизация, потому что ключ, передаваемый при авторизации на js живет час, а обновить его не выйдет (без участия юзера) т.к. не передается refresh token. Так же, рекомендую использовать одну из готовых библиотек, с ними все будет гораздо проще.

Первым делом создадим аккаунт. Перейдите на страницу console.developers.google.com, здесь в левом верхнем углу выберите проекты и нажмите «Создать проект».

Получение сообщений из трансляций youtube + авторизация google на PHP - 2

Введите название и сохраните. Теперь выберите свой проект и кликните «Включить API и сервисы» или перейдите на страницу библиотеки API
Здесь в поисковом запросе найдите и включите YouTube Data API v3.

После чего во вкладке «Окно запроса доступа OAuth» на левой панели в консоли (или тут) создайте окно.
На первом шаге выберите для User Type «Внешний»

Получение сообщений из трансляций youtube + авторизация google на PHP - 3

Далее, в этой форме необходимо заполнить 2 поля — название приложения и «Авторизованные домены», если у вас есть домен, можете оставить поле пустым, если таковых нет. Нажимаете сохранить. В результате должно получиться что-то вроде

Получение сообщений из трансляций youtube + авторизация google на PHP - 4

Теперь перейдите на вкладку «Учетные данные» (https://console.developers.google.com/apis/credentials)

Здесь вас встретит такая страница:

Получение сообщений из трансляций youtube + авторизация google на PHP - 5

Выберите кнопку «Создать учетные данные» -> «Идентификатор клиента OAuth»
Выберите нужный тип (для нас веб), введите название и «Разрешенные URI перенаправления» — это url на который будет отправляться код для авторизации клиента. Вы можете прописать сюда локальный url на время разработки, в моем случае это будет

http://localhost:8080/oauth2callback.php

Результат

Получение сообщений из трансляций youtube + авторизация google на PHP - 6

После должно появиться окно с ID клиента и Секретным ключом. Пока это смело закрываем. Перед вами страница с учетными данными, только что созданными

Получение сообщений из трансляций youtube + авторизация google на PHP - 7

Нажимайте на кнопочку «Скачать» для идентификатора:

Получение сообщений из трансляций youtube + авторизация google на PHP - 8

Можете сразу переименовать в secret_json.json.

На этом с настройкой авторизации покончено, теперь приступаем к коду.

PHP

Создайте проект, откройте терминал и запустите команду:

php composer.phar require google/apiclient:^2.0

Если вы не знаете что такое composer и как с его помощью устанавливать — знакомьтесь
После установки создайте 2 файла — index.php и oauth2callback.php
Можете, кстати, уже запустить ваш PHP сервер:

php -S localhost:8080

Так же переместите файл secret_json.json (который вы скачали ранее) в папку проекта.

Непосредственно на Index.php вы будете отправлять пользователя для авторизации. Содержание файла index.php

<?php
require_once __DIR__ . '/vendor/autoload.php';

$client = new Google_Client();
// это путь до нашего файла
$client->setAuthConfig('client_secret.json');
// чуть позже расскажу
$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);
// Требуется для получения refresh_token
$client->setAccessType("offline");

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
    $client->setAccessToken($_SESSION['access_token']);
} else {
    $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
    header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
    exit();
}

$refreshToken = $_SESSION['access_token']['refresh_token'];
$accessToken = $_SESSION['access_token']['access_token'];
$tknType = $_SESSION['access_token']['token_type'];
$clientId = $client->getClientId();
$created = $_SESSION['access_token']['created'];
unset($_SESSION['access_token']);
unset($_SESSION['user']);
session_destroy();

$data = json_encode([
  'refreshToken' => $refreshToken,
    'accessToken' => $accessToken,
    'tknType' => $tknType,
    'clientId' => $clientId,
    'created' => $created
]);
echo $data;

По сути, этот код отдаст пользователю все необходимые данные, вы же можете их записать в базу (или блокнот).

Файл oauth2callback.php:

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('client_secret.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);
$client->setApprovalPrompt('force');
$client->setAccessType("offline");

if (!isset($_GET['code'])) {
    $auth_url = $client->createAuthUrl();
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
    $client->authenticate($_GET['code']);
    $_SESSION['access_token'] = $client->getAccessToken();
    $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
    header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

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

На этом с авторизацией покончено. У вас уже есть access_token и refresh_token, давайте возьмемся за ютуб.

Ютубе

Сразу PHP

getStreams.php:

<?php
require_once __DIR__ . '/vendor/autoload.php';
// об этом позже
require_once __DIR__ . '/refreshToken.php';

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);
$client->setAccessType("offline");

// массив $data содержит информацию после прошлой авторизации (я пишу в бд)
if (($data['created'] - time()) <= -3600) {
    $data = refreshToken($data['refreshToken'], $db);
}

$client->setAccessToken($data['accessToken']);
$service = new Google_Service_YouTube($client);
// делаем 2 запроса потому что гугол отдает или идущие или запланированные трансляции, 
// но нам нужны и те и другие.
$queryParams = [
    'broadcastStatus' => 'upcoming',
    'maxResults' => 50
];
$response = $service->liveBroadcasts->listLiveBroadcasts('id,snippet,status', $queryParams);
$items = $response['items'];
$streamsUpcoming = itemsGenerator($items);

$queryParams = [
    'broadcastStatus' => 'active',
    'maxResults' => 50
];
$response = $service->liveBroadcasts->listLiveBroadcasts('id,snippet,status', $queryParams);
$items = $response['items'];
$streamsActive = itemsGenerator($items);
$streams = array_merge($streamsUpcoming, $streamsActive);

// отдаем данные
echo json_encode($streams);

// приводим ответ гугла к виду, который требуется нам.
function itemsGenerator($items) {
    $streams = [];
    foreach ($items as $item) {
        // значит трансляция в эфире или заплпнированна (законченные не выводим)
        if (!isset($item['snippet']['actualEndTime'])) {
            $streams[] = [
                'id' => $item['id'],
                'title' => $item['snippet']['title'],
                'description' => $item['snippet']['description'],
                'image' => $item['snippet']['thumbnails']['medium']['url'],
                'liveChatId' => $item['snippet']['liveChatId'],
                'channelId' => $item['snippet']['channelId']
            ];
        }
    }
    return $streams;
}

Помните вот эти строки еще при авторизации?

$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);

Так вот, они отвечают за то какой доступ вам требуется. Например, такая запись разрешает только чтение информации, есть еще https://www.googleapis.com/auth/youtube.upload и другие.

refreshToken.php:

<?php
require_once __DIR__ . '/vendor/autoload.php';

/**
 * @param string $refreshToken
 * @param $db
 * @return array
 * @throws Google_Exception
 */
function refreshToken($refreshToken, $db)
{
    $client = new Google_Client();
    $client->setAuthConfig('client_secret.json');
    $client->setScopes([
        'https://www.googleapis.com/auth/youtube.readonly',
    ]);
    $client->setAccessType("offline");

    $client->refreshToken($refreshToken);
    $accessToken = $client->getAccessToken();

    $refreshToken = $accessToken['refresh_token'];
    $accessToken = $accessToken['access_token'];
    $clientId = $client->getClientId();
    $data = [
        'refreshToken' => $refreshToken,
        'accessToken' => $accessToken,
        'tknType' => 'Bearer',
        'clientId' => $clientId,
        'created' => time()
    ];

    // тут можно перезаписать значение в бд, например.

    return $data;
}

Токен, выданный гуглом действует только час. В течении суток вы можете сделать только 25 запросов на обновление токена, эта функция как раз обновляет наш токен и возвращает новые значения с которыми и можно будет продолжать работать. В getStreams демонстрируется его работа.

И наконец
getStreamMessages.php:

<?php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/refreshToken.php';

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);
$client->setAccessType("offline");
// $data - массив с авторизационными данными из бд
if (($data['created'] - time()) <= -3600) {
    $data = refreshToken($data['refreshToken'], $db);
}
$client->setAccessToken($data['accessToken']);

$service = new Google_Service_YouTube($client);

$queryParams = [
    'maxResults' => 2000,
    'profileImageSize' => 120
];

$response = $service->liveChatMessages->listLiveChatMessages($liveChatId, 'id,snippet,authorDetails', $queryParams);

echo json_encode($response);

Здесь я уже не стал приводить в нужный формат сообщения, можете заняться этим сами, в массиве $response содержится вся нужная информация, а ссылка на статью вот.

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

Так же, я рекомендую прочесть документацию liveChatMessages, в нем присутствуют некоторые ограничения, вроде делать нужно запрос на каждую страницу с новым кодом который пришел в предыдущем запросе.

Github проект с бд (останется только закинуть файл client_secret.json)

Автор: Александр

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js