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';
|
|
|
|
|
|
2019-07-07 18:49:11 +00:00
|
|
|
|
// Récupère le chemin vers le fichier de sortie depuis la ligne de commande
|
|
|
|
|
if (process.argv.length !== 3)
|
|
|
|
|
{
|
|
|
|
|
console.error(`Utilisation : node src [sortie]`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const dest = process.argv[2];
|
|
|
|
|
|
2017-04-02 00:54:46 +00:00
|
|
|
|
// 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 d’une vidéo pour remplir le graphe
|
|
|
|
|
* des vidéos.
|
|
|
|
|
*
|
|
|
|
|
* @param videoId Identifiant de la vidéo source.
|
|
|
|
|
*/
|
|
|
|
|
const exploreVideo = videoId =>
|
|
|
|
|
{
|
|
|
|
|
// S’assure 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);
|
|
|
|
|
|
|
|
|
|
// 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 l’exploration !');
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
console.log('Terminé. Résultat dans ' + dest);
|
2017-04-02 00:54:46 +00:00
|
|
|
|
}).catch(console.error);
|