mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
Support YouTube takeout JSON
This commit is contained in:
parent
08842c4ba8
commit
bd5adf6652
2 changed files with 43 additions and 13 deletions
|
@ -6,12 +6,24 @@ const LBRY_API_HOST = 'https://api.lbry.com';
|
|||
const QUERY_CHUNK_SIZE = 300;
|
||||
|
||||
interface YtResolverResponse {
|
||||
success: boolean
|
||||
error: object | null
|
||||
success: boolean;
|
||||
error: object | null;
|
||||
data: {
|
||||
videos?: Record<string, string>
|
||||
channels?: Record<string, string>
|
||||
}
|
||||
videos?: Record<string, string>;
|
||||
channels?: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
interface YtSubscription {
|
||||
id: string;
|
||||
etag: string;
|
||||
title: string;
|
||||
snippet: {
|
||||
description: string;
|
||||
resourceId: {
|
||||
channelId: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,15 +53,29 @@ export const ytService = {
|
|||
* Reads the array of YT channels from an OPML file
|
||||
*
|
||||
* @param opmlContents an opml file as as tring
|
||||
* @returns the channel URLs
|
||||
* @returns the channel IDs
|
||||
*/
|
||||
readOpml(opmlContents: string): string[] {
|
||||
const opml = new DOMParser().parseFromString(opmlContents, 'application/xml');
|
||||
|
||||
return Array.from(opml.querySelectorAll('outline > outline'))
|
||||
.map(outline => outline.getAttribute('xmlUrl'))
|
||||
.filter((url): url is string => !!url)
|
||||
.map(url => ytService.getChannelId(url))
|
||||
.filter((url): url is string => !!url); // we don't want it if it's empty
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads an array of YT channel IDs from the YT subscriptions JSON file
|
||||
*
|
||||
* @param jsonContents a JSON file as a string
|
||||
* @returns the channel IDs
|
||||
*/
|
||||
readJson(jsonContents: string): string[] {
|
||||
const subscriptions: YtSubscription[] = JSON.parse(jsonContents);
|
||||
return subscriptions.map(sub => sub.snippet.resourceId.channelId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extracts the channelID from a YT URL.
|
||||
*
|
||||
|
@ -89,7 +115,7 @@ export const ytService = {
|
|||
video_ids: groups['video']?.map(s => s.id).join(','),
|
||||
channel_ids: groups['channel']?.map(s => s.id).join(','),
|
||||
}));
|
||||
return fetch(`${LBRY_API_HOST}/yt/resolve?${params}`, {cache: 'force-cache'})
|
||||
return fetch(`${LBRY_API_HOST}/yt/resolve?${params}`, { cache: 'force-cache' })
|
||||
.then(rsp => rsp.ok ? rsp.json() : null);
|
||||
}));
|
||||
|
||||
|
|
|
@ -5,16 +5,19 @@ import { getSettingsAsync, redirectDomains } from '../common/settings';
|
|||
import { YTDescriptor, getFileContent, ytService } from '../common/yt';
|
||||
|
||||
/**
|
||||
* Parses OPML file and queries the API for lbry channels
|
||||
* Parses the subscription file and queries the API for lbry channels
|
||||
*
|
||||
* @param file to read
|
||||
* @returns a promise with the list of channels that were found on lbry
|
||||
*/
|
||||
async function lbryChannelsFromOpml(file: File): Promise<string[]> {
|
||||
const lbryUrls = await ytService.resolveById(...ytService.readOpml(await getFileContent(file))
|
||||
.map(url => ytService.getId(url))
|
||||
.filter((id): id is YTDescriptor => !!id));
|
||||
async function lbryChannelsFromFile(file: File) {
|
||||
const ext = file.name.split('.').pop()?.toLowerCase();
|
||||
const content = await getFileContent(file);
|
||||
|
||||
const ids: YTDescriptor[] = (ext === 'xml' || ext == 'opml' ? ytService.readOpml(content) : ytService.readJson(content))
|
||||
.map(id => ({ id, type: 'channel' }));
|
||||
|
||||
const lbryUrls = await ytService.resolveById(...ids);
|
||||
const { redirect } = await getSettingsAsync('redirect');
|
||||
const urlPrefix = redirectDomains[redirect].prefix;
|
||||
return lbryUrls.map(channel => urlPrefix + channel);
|
||||
|
@ -24,6 +27,7 @@ function YTtoLBRY() {
|
|||
const [file, setFile] = useState(null as File | null);
|
||||
const [lbryChannels, setLbryChannels] = useState([] as string[]);
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
|
||||
return <>
|
||||
<iframe width="100%" height="400px" allowFullScreen
|
||||
src="https://lbry.tv/$/embed/howtouseconverter/c9827448d6ac7a74ecdb972c5cdf9ddaf648a28e" />
|
||||
|
@ -35,7 +39,7 @@ function YTtoLBRY() {
|
|||
<input type="button" value="Start Conversion!" class="goButton" disabled={!file || isLoading} onClick={async () => {
|
||||
if (!file) return;
|
||||
setLoading(true);
|
||||
setLbryChannels(await lbryChannelsFromOpml(file));
|
||||
setLbryChannels(await lbryChannelsFromFile(file));
|
||||
setLoading(false);
|
||||
}} />
|
||||
<ul>
|
||||
|
|
Loading…
Add table
Reference in a new issue