import express from 'express'; import { exploreVideos, toGraphviz } from '../lib/explore.mjs'; import { toSVG } from '../lib/graphviz.mjs'; const router = express.Router(); export default router; const statusDone = Symbol('DONE'); const statusPending = Symbol('PENDING'); const statusError = Symbol('ERROR'); const cache = Object.create(null); // Extract the video ID from a YouTube URL const YOUTUBE_URL_REGEX = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?v=([^?&]+)/; const YOUTUBE_SHORT_URL_REGEX = /(?:https?:\/\/)?(?:www\.)?youtu\.be\/([^?&]+)/; router.post('/', (req, res) => { if (req.body.url === '') { res.redirect('/'); return; } const url = req.body.url.match(YOUTUBE_URL_REGEX); if (url !== null) { res.redirect(`/mazes/${url[1]}`); return; } const shortURL = req.body.url.match(YOUTUBE_SHORT_URL_REGEX); if (shortURL !== null) { res.redirect(`/mazes/${shortURL[1]}`); return; } res.redirect(`/mazes/${req.body.url}`); }); // Generate the graph for a given video ID router.get('/:videoId', async (req, res) => { const {videoId} = req.params; if (videoId in cache) { if (cache[videoId][0] === statusPending) { res.header('Refresh', '5'); res.send(`Exploration in progress, please wait.
${cache[videoId][1]}…`); } else if (cache[videoId][0] === statusError) { res.status(500).send('Error'); } else { res.send(cache[videoId][1]); } } else { cache[videoId] = [statusPending, 'Starting exploration']; res.header('Refresh', '1'); res.send('Exploration in progress, please wait.'); try { const graph = await exploreVideos(req.params.videoId, (done, rem) => { cache[videoId] = [ statusPending, `${done} videos explored, ${rem} pending` ]; }); cache[videoId] = [statusPending, 'Converting graph to SVG']; const graphviz = toGraphviz(...graph); const svg = await toSVG(graphviz); cache[videoId] = [statusDone, svg]; } catch (err) { console.error(err); cache[videoId] = [statusError]; } } });