youtube-maze/src/index.js

83 lines
2.3 KiB
JavaScript
Raw Normal View History

2017-04-02 00:54:46 +00:00
'use strict';
const Graph = require('graph-data-structure');
const fs = require('fs');
const path = require('path');
const util = require('util');
const {getEndScreenVideos, getCardVideos} = require('./api');
const {graphToDOT} = require('./graph');
const YOUTUBE_WATCH = 'https://youtu.be/%s';
// Graphe des vidéos. Chaque nœud est une vidéo, et est liée à toutes
// les vidéos vers lesquelles elle a un lien (par carte ou écran de fin)
const videosGraph = Graph();
// Stocke les métadonnées de chaque vidéo
const videosMeta = Object.create(null);
// Se souvient des vidéos déja visitées
const visitedVideos = Object.create(null);
/**
* Explore récursivement les liens dune vidéo pour remplir le graphe
* des vidéos.
*
* @param videoId Identifiant de la vidéo source.
*/
const exploreVideo = videoId =>
{
// Sassure de ne pas visiter deux fois la même vidéo
if (visitedVideos[videoId] === true)
{
return Promise.resolve();
}
visitedVideos[videoId] = true;
return Promise.all([
getEndScreenVideos(videoId),
getCardVideos(videoId)
]).then(results =>
{
const videos = [].concat(...results);
const ids = videos.map(video => video.videoId);
// const remaining = ids.filter(id => videos[id] === undefined);
// Ajout des vidéos liées dans les métadonnées
videos.forEach(video => videosMeta[video.videoId] = video);
// Ajout des liens entre la vidéo et ses vidéos liées
ids.forEach(id => videosGraph.addEdge(videoId, id));
// Récursion sur les vidéos non-explorées
return Promise.all(ids.map(id => exploreVideo(id)));
});
};
// Métadonnées de la vidéo source
const rootVideoId = 'EZGra6O8ClQ';
videosMeta[rootVideoId] = {
title: '1 avril 2017 : présentation des règles',
videoId: rootVideoId,
links: []
};
console.log('Démarrage de lexploration !');
exploreVideo(rootVideoId).then(() =>
{
const dest = path.join(__dirname, '../maze.dot');
console.log('Terminé. Résultat dans ' + dest);
fs.writeFileSync(
dest,
graphToDOT(
videosGraph,
id => videosMeta[id].title,
id => util.format(YOUTUBE_WATCH, id)
)
);
}).catch(console.error);