UNPKG

ytpl

Version:

Simple package to resolve YouTube playlists - no strings attached.

71 lines (63 loc) 2.85 kB
const PATH = require('path'); const FS = require('fs'); const UTIL = require('./utils.js'); const SKIP_TYPES = ['continuationItemRenderer']; const BASE_VIDEO_URL = 'https://www.youtube.com/watch?v='; const prepImg = UTIL.prepImg; const parseItem = item => { const type = Object.keys(item)[0]; if (SKIP_TYPES.includes(type)) return null; else if (type !== 'playlistVideoRenderer') throw new Error(`unexpected type "${type}"`); let info = item[type]; if (!info || !info.shortBylineText || info.upcomingEventData) return null; const isLive = info.thumbnailOverlays.some(a => a.thumbnailOverlayTimeStatusRenderer && a.thumbnailOverlayTimeStatusRenderer.style === 'LIVE'); const author = info.shortBylineText.runs[0]; return { title: UTIL.parseText(info.title, ''), index: info.index ? UTIL.parseIntegerFromText(info.index) : -1, id: info.videoId, shortUrl: BASE_VIDEO_URL + info.videoId, url: new URL(info.navigationEndpoint.commandMetadata.webCommandMetadata.url, BASE_VIDEO_URL).toString(), author: { url: new URL(author.navigationEndpoint.commandMetadata.webCommandMetadata.url, BASE_VIDEO_URL).toString(), channelID: author.navigationEndpoint.browseEndpoint.browseId, name: author.text, }, thumbnails: prepImg(info.thumbnail.thumbnails), bestThumbnail: prepImg(info.thumbnail.thumbnails)[0], isLive, duration: !info.lengthText ? null : UTIL.parseText(info.lengthText), durationSec: Number(info.lengthSeconds) || null, // No idea what this represents - guess a video that youtube hasn't recompiled yet isPlayable: info.isPlayable, }; }; const catchAndLogFunc = (func, params = []) => { if (!Array.isArray(params)) throw new Error('params has to be an (optionally empty) array'); try { return func(...params); } catch (e) { const dir = PATH.resolve(__dirname, '../dumps/'); const file = PATH.resolve(dir, `${Math.random().toString(36).substr(3)}-${Date.now()}.txt`); const cfg = PATH.resolve(__dirname, '../package.json'); const bugsRef = require(cfg).bugs.url; if (!FS.existsSync(dir)) FS.mkdirSync(dir); FS.writeFileSync(file, JSON.stringify(params, null, 2)); /* eslint-disable no-console */ console.error(e.stack); console.error(`\n/${'*'.repeat(200)}`); console.error(`failed at func ${func.name}: ${e.message}`); console.error(`pls post the the files in ${dir} to ${bugsRef}`); let info = `os: ${process.platform}-${process.arch}, `; info += `node.js: ${process.version}, `; info += `ytpl: ${require('../package.json').version}`; console.error(info); console.error(`${'*'.repeat(200)}\\`); /* eslint-enable no-console */ return null; } }; const main = module.exports = (...params) => catchAndLogFunc(parseItem, params); main._hidden = { catchAndLogFunc };