2020-07-15 17:31:09 +00:00
|
|
|
|
import fs from 'fs';
|
|
|
|
|
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
|
|
|
|
|
2020-07-15 17:14:31 +00:00
|
|
|
|
// Fetch the output path from command line
|
2020-11-27 23:17:04 +00:00
|
|
|
|
if (process.argv.length !== 4)
|
2019-07-07 18:49:11 +00:00
|
|
|
|
{
|
2020-11-27 23:17:04 +00:00
|
|
|
|
console.error(`Usage: ${process.argv[1]} ROOT DEST
|
|
|
|
|
Explore videos linked from ROOT and write the resulting graph to DEST.`);
|
2019-07-07 18:49:11 +00:00
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-27 23:17:04 +00:00
|
|
|
|
const root = process.argv[2];
|
|
|
|
|
const dest = process.argv[3];
|
2017-04-02 00:54:46 +00:00
|
|
|
|
|
2020-07-15 17:14:31 +00:00
|
|
|
|
// Store metadata about each visited video
|
2020-11-27 23:17:04 +00:00
|
|
|
|
const videosNodes = Object.create(null);
|
|
|
|
|
|
|
|
|
|
// List of videos linked from each video either through a card or an
|
|
|
|
|
// endscreen item
|
|
|
|
|
const nextVideos = Object.create(null);
|
2017-04-02 00:54:46 +00:00
|
|
|
|
|
|
|
|
|
/**
|
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 don’t explore the same video twice
|
2020-11-27 23:17:04 +00:00
|
|
|
|
if (videoId in videosNodes)
|
2017-04-02 00:54:46 +00:00
|
|
|
|
{
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-27 23:17:04 +00:00
|
|
|
|
videosNodes[videoId] = {};
|
2017-04-02 00:54:46 +00:00
|
|
|
|
|
2020-11-27 23:17:04 +00:00
|
|
|
|
const playerConfig = await api.getPlayerConfig(videoId);
|
|
|
|
|
videosNodes[videoId] = api.getVideoMeta(playerConfig);
|
|
|
|
|
nextVideos[videoId] = new Set();
|
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
|
2020-11-27 23:17:04 +00:00
|
|
|
|
api.getEndScreenVideos(playerConfig)
|
|
|
|
|
.forEach(nextId => nextVideos[videoId].add(nextId));
|
|
|
|
|
api.getCardVideos(playerConfig)
|
|
|
|
|
.forEach(nextId => nextVideos[videoId].add(nextId));
|
2017-04-02 00:54:46 +00:00
|
|
|
|
|
2020-07-15 17:14:31 +00:00
|
|
|
|
// Recurse on linked videos
|
2020-11-27 23:17:04 +00:00
|
|
|
|
return Promise.all(
|
|
|
|
|
Array.from(nextVideos[videoId])
|
|
|
|
|
.map(id => exploreVideo(id))
|
|
|
|
|
);
|
2017-04-02 00:54:46 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-07-15 17:14:31 +00:00
|
|
|
|
console.log('Starting to explore!');
|
2020-11-27 23:17:04 +00:00
|
|
|
|
exploreVideo(root).then(() =>
|
2017-04-02 00:54:46 +00:00
|
|
|
|
{
|
2020-11-27 23:17:04 +00:00
|
|
|
|
fs.writeFileSync(dest, graphToDOT(videosNodes, nextVideos));
|
|
|
|
|
console.log(`Finished. Result in ${dest}`);
|
2017-04-02 00:54:46 +00:00
|
|
|
|
}).catch(console.error);
|