This finally got annoying enough for me to get back to. I don’t have a great solution, but I’ve taken another step forward, so posting here in case it helps anyone, or someone can take the next step forwards.
I found the YouTube TV website gets its data from this page:
https://tv.youtube.com/youtubei/v1/unplugged/browse
I haven’t been able to call that directly without getting blocked by their automation detection. So what I’m doing now instead is to manually load the website (tv.youtube.com/live) with dev tools loaded, and copy/pasting the results of the above file to my server. So now I can get all the updated channels at once just by pulling/updating this file. Then I’ve written the attached php to parse the codes from their file into JSON that can be consumed in a REST sensor within HA.
<?php
$youtubeSource = 'browse.json';
$youtubeRaw = json_decode(file_get_contents($youtubeSource), true);
$returnValues = array();
foreach ($youtubeRaw["contents"]["epgRenderer"]["paginationRenderer"]["epgPaginationRenderer"]["contents"] as $channelObj) {
$channelName = $channelObj["epgRowRenderer"]["station"]["epgStationRenderer"]["icon"]["accessibility"]["accessibilityData"]["label"];
$channelValue = $channelObj["epgRowRenderer"]["airings"][0]["epgAiringRenderer"]["navigationEndpoint"]["watchEndpoint"]["videoId"];
if ($channelValue == "") {
$channelValue = $channelObj["epgRowRenderer"]["airings"][0]["epgAiringRenderer"]["navigationEndpoint"]["unpluggedPopupEndpoint"]["popupRenderer"]["unpluggedSelectionMenuDialogRenderer"]["items"][0]["unpluggedMenuItemRenderer"]["command"]["watchEndpoint"]["videoId"];
}
array_push($returnValues, ["name" => strtoupper(trim($channelName)), "value" => trim($channelValue)]);
}
if (empty($returnValues)) {
print '{"count":0,"channels":{}}';
} else {
printf('{"count":%s,"channels":{', count($returnValues) );
$hasPrinted = false;
foreach ($returnValues as $row) {
if ($hasPrinted)
print ', ';
printf('"%s": "%s"', $row["name"], $row["value"]);
$hasPrinted = true;
}
print '}}';
}
?>