youtube-maze/explore/index.mjs

73 lines
1.8 KiB
JavaScript
Raw Normal View History

2020-07-15 17:31:09 +00:00
import Graph from 'graph-data-structure';
import fs from 'fs';
import path from 'path';
import util from 'util';
2017-04-02 00:54:46 +00:00
2020-07-15 17:31:09 +00:00
import * as api from './api.mjs';
import {graphToDOT} from './graph.mjs';
2017-04-02 00:54:46 +00:00
const YOUTUBE_WATCH = 'https://youtu.be/%s';
2020-07-15 17:14:31 +00:00
// Fetch the output path from command line
2019-07-07 18:49:11 +00:00
if (process.argv.length !== 3)
{
2020-07-15 17:14:31 +00:00
console.error(`Usage: node explore [output]`);
2019-07-07 18:49:11 +00:00
process.exit(1);
}
const dest = process.argv[2];
2020-07-15 17:14:31 +00:00
// Graph of visited videos. Each node is a video which is linked to all the
// videos to which there is a link, either through a card or an endscreen item
2017-04-02 00:54:46 +00:00
const videosGraph = Graph();
2020-07-15 17:14:31 +00:00
// Store metadata about each visited video
2017-04-02 00:54:46 +00:00
const videosMeta = Object.create(null);
/**
2020-07-15 17:14:31 +00:00
* Recursively explore a video and the video linked from it to fill
* the video graph.
2017-04-02 00:54:46 +00:00
*
2020-07-15 17:14:31 +00:00
* @param videoId Source video identifier.
2017-04-02 00:54:46 +00:00
*/
2020-07-15 17:14:31 +00:00
const exploreVideo = async videoId =>
2017-04-02 00:54:46 +00:00
{
2020-07-15 17:14:31 +00:00
// Make sure we dont explore the same video twice
if (videoId in videosMeta)
2017-04-02 00:54:46 +00:00
{
return Promise.resolve();
}
2020-07-15 17:14:31 +00:00
const playerConfig = await api.getPlayerConfig(videoId);
videosMeta[videoId] = api.getVideoMeta(playerConfig);
2017-04-02 00:54:46 +00:00
2020-07-15 17:14:31 +00:00
const linkedVideos = [
...api.getEndScreenVideos(playerConfig),
...api.getCardVideos(playerConfig),
];
2017-04-02 00:54:46 +00:00
2020-07-15 17:14:31 +00:00
// Add links between this video and the linked ones
linkedVideos.forEach(id => videosGraph.addEdge(videoId, id));
2017-04-02 00:54:46 +00:00
2020-07-15 17:14:31 +00:00
// Recurse on linked videos
return Promise.all(linkedVideos.map(id => exploreVideo(id)));
2017-04-02 00:54:46 +00:00
};
2020-07-15 17:14:31 +00:00
// Metadata of the source video
2017-04-02 00:54:46 +00:00
const rootVideoId = 'EZGra6O8ClQ';
2020-07-15 17:14:31 +00:00
console.log('Starting to explore!');
2017-04-02 00:54:46 +00:00
exploreVideo(rootVideoId).then(() =>
{
fs.writeFileSync(
dest,
graphToDOT(
videosGraph,
id => videosMeta[id].title,
id => util.format(YOUTUBE_WATCH, id)
)
);
2019-07-07 18:49:11 +00:00
2020-07-15 17:14:31 +00:00
console.log('Finished. Result in ' + dest);
2017-04-02 00:54:46 +00:00
}).catch(console.error);