Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix members only stream error & update video metadata #15

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
],
"dependencies": {
"axios": "^0.27.2",
"cheerio": "^1.0.0-rc.12",
"debug": "^4.3.2",
"iterator-helpers-polyfill": "^2.2.8",
"sha1": "^1.1.1"
Expand Down
58 changes: 56 additions & 2 deletions src/context/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as cheerio from "cheerio";
import {
MembersOnlyError,
NoPermissionError,
Expand Down Expand Up @@ -107,7 +108,7 @@ export function parseMetadataFromWatch(html: string) {
const initialData = findInitialData(html)!;

const playabilityStatus = findPlayabilityStatus(html);
assertPlayability(playabilityStatus);
// assertPlayability(playabilityStatus);

// TODO: initialData.contents.twoColumnWatchNextResults.conversationBar.conversationBarRenderer.availabilityMessage.messageRenderer.text.runs[0].text === 'Chat is disabled for this live stream.'
const results =
Expand All @@ -120,7 +121,8 @@ export function parseMetadataFromWatch(html: string) {
const title = runsToString(primaryInfo.title.runs);
const channelId = videoOwner.navigationEndpoint.browseEndpoint.browseId;
const channelName = runsToString(videoOwner.title.runs);
const isLive = primaryInfo.viewCount!.videoViewCountRenderer.isLive ?? false;
const metadata = parseVideoMetadataFromHtml(html);

Choose a reason for hiding this comment

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

you parsed the metadata but I don't think you're exposing it anywhere at all?

Copy link
Author

@HitomaruKonpaku HitomaruKonpaku Nov 30, 2022

Choose a reason for hiding this comment

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

Currently we just return simple data (title/channelId/channelName)

But I just think we can return full metadata in case anyone need 🤔

const isLive = !metadata?.publication?.endDate ?? false;

return {
title,
Expand All @@ -129,3 +131,55 @@ export function parseMetadataFromWatch(html: string) {
isLive,
};
}

/**
* @see http://schema.org/VideoObject
*/
function parseVideoMetadataFromHtml(html: string) {
const $ = cheerio.load(html);
const meta = parseVideoMetadataFromElement(
$("[itemtype=http://schema.org/VideoObject]")?.[0]
);
return meta;
}

function parseVideoMetadataFromElement(
root: any,
meta: Record<string, any> = {}
) {
root?.children?.forEach((child: cheerio.Element) => {
const attributes = child?.attribs;
const key = attributes?.itemprop;
if (!key) {
return;
}

if (child.children.length) {
meta[key] = parseVideoMetadataFromElement(child);
return;
}

const value = parseVideoMetaValueByKey(
key,
attributes?.href || attributes?.content
);
meta[key] = value;
});

return meta;
}

function parseVideoMetaValueByKey(key: string, value: string) {
switch (key) {
case "paid":
case "unlisted":
case "isFamilyFriendly":
case "interactionCount":
case "isLiveBroadcast":
return /true/i.test(value);
case "width":
case "height":
return Number(value);
}
return value;
}