youtube-maze/src/api.js

110 lines
3.2 KiB
JavaScript
Raw Normal View History

2017-04-02 00:54:46 +00:00
'use strict';
const util = require('util');
const request = require('request');
const cheerio = require('cheerio');
const YOUTUBE_BASE = 'https://www.youtube.com/%s';
const VIDEO_ID_REGEX = /watch\?v=([^&]*)/i;
const END_SCREEN_BASE = util.format(YOUTUBE_BASE, 'get_endscreen?v=%s');
const CARD_BASE = util.format(YOUTUBE_BASE, 'annotations_invideo?video_id=%s');
/**
* Récupère une liste des vidéos liées à la fin dune autre vidéo.
*
* @param videoId Identifiant de la vidéo source.
* @return Liste des vidéos liées. Chaque vidéo est un objet contenant
* son identifiant (videoId) et son titre (title).
*/
const getEndScreenVideos = videoId =>
{
const url = util.format(END_SCREEN_BASE, videoId);
return new Promise((resolve, reject) =>
{
request(url, (err, res, body) =>
{
if (err)
{
reject(err);
return;
}
// Suppression des caractères initiaux inutiles si applicable
if (body.substr(0, 3) === ')]}')
{
body = body.substr(3);
}
// Interprétation du JSON
const data = JSON.parse(body);
// Aucun écran de fin
if (
typeof data !== 'object' || data === null ||
data.elements === undefined
)
{
resolve([]);
return;
}
// Filtrage des données pour extraire le titre et lID des vidéos
resolve(data.elements.map(elt => ({
videoId: elt.endscreenElementRenderer.endpoint
.watchEndpoint.videoId,
2017-07-14 14:55:02 +00:00
title: elt.endscreenElementRenderer.title.simpleText,
2017-04-02 00:54:46 +00:00
})));
});
});
};
exports.getEndScreenVideos = getEndScreenVideos;
/**
* Récupère une liste des vidéos liées en tant que carte dune autre vidéo.
*
* @param videoId Identifiant de la vidéo source.
* @return Liste des vidéos liées. Chaque vidéo est un objet contenant
* son identifiant (videoId) et son titre (title).
*/
const getCardVideos = videoId =>
{
const url = util.format(CARD_BASE, videoId);
return new Promise((resolve, reject) =>
{
request(url, (err, res, body) =>
{
if (err)
{
reject(err);
return;
}
// Interprétation du XML externe et recherche des annotations
// de type carte
const nav = cheerio.load(body);
const cards = nav('annotation[type="card"][style="video"]');
const list = [];
cards.each((i, el) =>
{
// Interprétation du JSON de chaque carte, extraction
// du titre et de lidentifiant de la vidéo
const data = JSON.parse(nav(el).children('data').text());
const videoIdResults = VIDEO_ID_REGEX.exec(data.url);
list.push({
title: data.title,
videoId: videoIdResults ? videoIdResults[1] : null
});
});
resolve(list);
});
});
};
exports.getCardVideos = getCardVideos;