Skip to content

Commit

Permalink
Add Protobuf dependency and authentication to retrieve community post…
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin-Loison committed Mar 31, 2024
1 parent d24a69a commit 9a607a3
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 6 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,37 @@ brew services start httpd
git clone https://github.com/Benjamin-Loison/YouTube-operational-API
```

4. Verify that your API instance is reachable by trying to access:
4. Install Protobuf dependency:

### On Linux (Ubuntu, Debian and Mint):

```sh
sudo apt install composer
```

### On Windows:

TODO

### On MacOS:

```sh
brew install composer
```

In `YouTube-operational-API/` clone folder:

```sh
composer require google/protobuf
```

Generate code of PHP objects from `.proto` prototypes:

```sh
protoc --php_out=proto/php/ --proto_path=proto/prototypes/ $(find proto/prototypes/ -type f)
```

5. Verify that your API instance is reachable by trying to access:

- On Linux and Windows: http://localhost/YouTube-operational-API/
- On MacOS: http://localhost:8080/YouTube-operational-API/
Expand Down
4 changes: 4 additions & 0 deletions common.php
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ function getCommunityPostFromContent($content)
foreach ($pollRenderer['choices'] as $choice) {
$returnedChoice = $choice['text']['runs'][0];
$returnedChoice['image'] = $choice['image'];
$returnedChoice['voteRatio'] = $choice['voteRatioIfNotSelected'];
array_push($choices, $returnedChoice);
}
$totalVotesStr = $pollRenderer['totalVotes']['simpleText'];
Expand All @@ -394,6 +395,9 @@ function getCommunityPostFromContent($content)
$post = [
'id' => $id,
'channelId' => $channelId,
'channelName' => $common['authorText']['runs'][0]['text'],
'channelHandle' => substr($common['authorEndpoint']['browseEndpoint']['canonicalBaseUrl'], 1),
'channelThumbnails' => $common['authorThumbnail']['thumbnails'],
'date' => $date,
'contentText' => $contentText,
'likes' => $likes,
Expand Down
68 changes: 63 additions & 5 deletions community.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

header('Content-Type: application/json; charset=UTF-8');

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

include_once 'proto/php/Browse.php';
include_once 'proto/php/GPBMetadata/Browse.php';
include_once 'proto/php/SubBrowse.php';
include_once 'proto/php/GPBMetadata/SubBrowse.php';

include_once 'common.php';

$realOptions = [
Expand All @@ -12,7 +19,7 @@
$options[$realOption] = false;
}

if (isset($_GET['part'], $_GET['id'])) {
if (isset($_GET['part'], $_GET['id'], $_GET['channelId'])) {
$part = $_GET['part'];
$parts = explode(',', $part, count($realOptions));
foreach ($parts as $part) {
Expand All @@ -28,20 +35,71 @@
dieWithJsonMessage('Invalid postId');
}

$channelId = $_GET['channelId'];
if (!isChannelId($channelId)) {
dieWithJsonMessage('Invalid channelId');
}

$order = isset($_GET['order']) ? $_GET['order'] : 'relevance';
if (!in_array($order, ['relevance', 'time'])) {
dieWithJsonMessage('Invalid order');
}

echo getAPI($postId, $order);
echo getAPI($postId, $channelId, $order);
} else if(!test()) {
dieWithJsonMessage('Required parameters not provided');
}

function getAPI($postId, $order)
function implodeArray($anArray, $separator)
{
return array_map(fn($k, $v) => "${k}${separator}${v}", array_keys($anArray), array_values($anArray));
}

function getAPI($postId, $channelId, $order)
{
$result = getJSONFromHTMLForcingLanguage("https://www.youtube.com/post/$postId");
$contents = getTabs($result)[0]['tabRenderer']['content']['sectionListRenderer']['contents'];
$currentTime = time();
$SAPISID = 'CENSORED';
$__Secure_3PSID = 'CENSORED';
$ORIGIN = 'https://www.youtube.com';
$SAPISIDHASH = "${currentTime}_" . sha1("$currentTime $SAPISID $ORIGIN");

$subBrowse = new \SubBrowse();
$subBrowse->setPostId($postId);

$browse = new \Browse();
$browse->setEndpoint('community');
$browse->setSubBrowse($subBrowse);

$params = base64_encode($browse->serializeToString());

$rawData = [
'context' => [
'client' => [
'clientName' => 'WEB',
'clientVersion' => MUSIC_VERSION
]
],
'browseId' => $channelId,
'params' => $params,
];

$opts = [
'http' => [
'method' => 'POST',
'header' => implodeArray([
'Content-Type' => 'application/json',
'Origin' => $ORIGIN,
'Authorization' => "SAPISIDHASH $SAPISIDHASH",
'Cookie' => implode('; ', implodeArray([
'__Secure-3PSID' => $__Secure_3PSID,
'__Secure-3PAPISID' => $SAPISID,
], '=')),
], ': '),
'content' => json_encode($rawData),
]
];
$result = getJSON('https://www.youtube.com/youtubei/v1/browse', $opts);
$contents = getTabByName($result, 'Community')['tabRenderer']['content']['sectionListRenderer']['contents'];
$content = $contents[0]['itemSectionRenderer']['contents'][0];
$post = getCommunityPostFromContent($content);
$continuationToken = urldecode($contents[1]['itemSectionRenderer']['contents'][0]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token']);
Expand Down
1 change: 1 addition & 0 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ function feature($feature)
'snippet',
],
'id' => 'POST_ID',
'channelId' => 'CHANNEL_ID',
'order' => [
'relevance',
'time',
Expand Down

2 comments on commit 9a607a3

@Benjamin-Loison
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Benjamin-Loison
Copy link
Owner Author

@Benjamin-Loison Benjamin-Loison commented on 9a607a3 Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing proto/prototypes/!

Solved.

Please sign in to comment.