youtube-maze/explore/api.js

117 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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 =>
{
const data = elt.endscreenElementRenderer;
const videoIdResults = VIDEO_ID_REGEX.exec(
data.endpoint.urlEndpoint.url
);
return {
videoId: videoIdResults ? videoIdResults[1] : null,
title: data.title.simpleText,
};
}));
});
});
};
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;