Receiving messages from youtube broadcasts + google authorization in PHP

The other day there was a task of receiving messages from youtube stream. I did not find articles on this subject, but there are only offs. google documentation I figured it out (I hope) and am ready to share my experience with you.

image

The first thing I found was the LiveChatMessages: list method , it would seem that everything is simple, but the required parameter is to pass liveChatId, which you can get by making a request to LiveBroadcasts: list , but to make a request there, you need to authorize the user through google with access to reading account. In the examples, everything is spelled out in detail, but if you are reading this article, it may not be as clear as we would like.

Login


Google console


Using OAuth 2.0 for Web Server Applications , I want to note right away that Web Server authorization is required, because the key transmitted during authorization to js lasts an hour, and it won’t be updated (without user participation) because refresh token is not transmitted. Also, I recommend using one of the ready-made libraries, everything will be much easier with them.

First, create an account. Go to console.developers.google.com , select the projects in the upper left corner and click "Create Project".



Enter a name and save. Now select your project and click “Enable APIs and Services” or go to the API library page.
Here, in the search query, find and enable the YouTube Data API v3.

Then, in the "OAuth Access Request Window" tab in the left pane of the console ( or here ), create a window.
At the first step, select “External” for the User Type.



Next, in this form you need to fill in 2 fields - the name of the application and “Authorized domains”, if you have a domain, you can leave the field empty if there are none. Click save. The result should be something like



Now go to the "Credentials" tab (https://console.developers.google.com/apis/credentials)

Here you will find such a page:



Select the "Create Credentials" button -> "Identifier OAuth Client »
Select the type you want (for us, the web), enter the name and "Allowed redirect URIs" - this is the url to which the code will be sent to authorize the client. You can write here a local url at the time of development, in my case it will be
http: // localhost: 8080 / oauth2callback.php

Result




After that, a window with the client ID and the Secret key should appear. While this is safely closing. Here is a page with the credentials just created.



Click on the Download button for an identifier:



You can immediately rename it to secret_json.json.

This is done with setting up authorization, now let's get down to the code.

Php


Create a project, open a terminal and run the command:

php composer.phar require google/apiclient:^2.0

If you don’t know what composer is and how to install it, get acquainted.
After installation, create 2 files - index.php and oauth2callback.php. By the
way, you can already start your PHP server:

php -S localhost:8080

Also move the file secret_json.json (which you downloaded earlier) to the project folder.

Directly on Index.php you will send the user for authorization. Index.php File Contents

<?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;

In fact, this code will give the user all the necessary data, you can write them to the database (or notepad).

File 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));
}

This file will redirect the user to the Google authorization page and write the token data to the session. After, it will return the user back to where index.php will continue to work with them.
Of course, you can write all the data directly to oauth2callback and not redirect the user back to index, or you can specify the next point with any address convenient for you. Also, authorization errors were not taken into account in this code, keep this in mind.

This is done with authorization. You already have access_token and refresh_token, let's get YouTube.

Youtube


PHP right away


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;
}


Remember these lines during authorization?

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

So, they are responsible for what kind of access you require. For example, such a record allows only reading information, there are https://www.googleapis.com/auth/youtube.uploadothers.

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;
}

The token issued by Google is valid only for an hour. During the day you can make only 25 requests for updating the token, this function just updates our token and returns new values ​​with which you can continue to work. GetStreams demonstrates its work.

And finally
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);

Here I didn’t begin to bring the message format to the desired format, you can do it yourself, the $ response array contains all the necessary information, and the link to the article is here .

What upset me is that there is no method for getting hooks (if there is one, leave a link, please) and you have to make constant requests.

Also, I recommend reading the documentation of liveChatMessages, there are some restrictions in it, like you need to make a request for each page with a new code that came in the previous request.

Github project with db (all that remains is to upload the client_secret.json file)

All Articles